面向对象特征之多态&内部类
1、定义
某一类事物的多种存在形态。
对象的多态性,就是一个对象对应着不同类型
例子:动物中猫,狗
猫这个对象对应的类型是猫类型
猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫称为动物
动物 y = new猫();
动物是猫和狗具体事物中抽取出来的父类型;
父类型引用指向了子类对象。
2、多态在代码中的体现:
*父类或者接口的引用指向了其子类的对象。
多态举例:毕老师和毕姥爷的故事。
class 毕姥爷{
void 讲课(){
System.out.println("管理");
}
void 钓鱼(){
System.out.println("钓鱼");
}
}
class 毕老师 extends 毕姥爷{
void 讲课(){
System.out.println("Java");
}
void 看电影(){
System.out.println("看电影");
}
}
class DuoTaiDemo{
public static void main(String[] args){
// 毕老师 x = new 毕老师();
// x.讲课();
// x.看电影();
毕姥爷 x = new 毕老师();
x.讲课();//讲课执行的毕老师的方法“Java”
x.钓鱼();
毕老师 y = (毕老师)x;
y.看电影();
}
}
3、多态的好处:
*提高了代码的扩展性,前期定义的代码可以使用后期的内容。
*提高了程序的后期可维护性。
4、多态的弊端:
前期定义的内容不能使用(调用)后期子类的特有内容
5、多态的前提:
*需要存在继承或实现关系
*要有覆盖操作
6、多态的特点:
*成员变量
只看引用变量所属的类。
编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边。
*成员函数(非静态)
编译时:参考引用型变量所属的类中是否有调用的函数。有,编译通过,没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。
因为成员函数存在覆盖特性。
*静态函数
编译时:参考引用型变量所属的类中是否有调用的静态方法;
运行时:参考引用型变量所属的类中是否有调用的静态方法。
简单说:编译和运行都看左边。
其实对于静态方法,是不需要对象的。直接用类名调用即可。
除了成员函数(非静态)是编译看左边,运行看右边,其他都是编译运行都看左边。
7、转型(重点掌握)
(1)多态:
向上转型,作用是限制对特有功能的访问,隐藏子类
向下转型,目的是为了使用子类中的特有方法。
(2)注意:对于转型,自始至终都是子类对象在做着类型的变化。
instanceof:用于判断对象的具体类型,只能用于引用数据类型判断,通常在向下转型前用于健壮性的判断。(由instance和of两个单词组成)
Animal a = new Cat();//自动类型提升,猫对象提升了动物类型。但是特有功能无法访问。
作用就是限制对特有功能的访问。
专业讲:向上转型。将子类型隐藏,就不用使用子类的特有方法。
Cat c = (Cat)a;//如果还想用具体动物猫的特有功能,可以将该对象进行向下转型。
向下转型的目的是为了使用子类中的特有方法。
8、内部类:
(1)将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类);
(2)内部类访问特点:
*内部类可以直接访问外部类中的成员,包括私有成员
*外部类要访问内部类,必须建立内部类的对象。
(3)内部类的位置:
*内部类定义在成员位置上
**可以被private static成员修饰符修饰
**被static修饰的内部类只能访问外部类中的静态成员。
*内部类定义在局部位置上
**也可以直接访问外部类中的成员;
**同时可以访问所在局部中的局部变量,但必须是被final修饰的(因为局部变量若没被final修饰,会用完就释放,这样内部类就不能访问了)
(4)作用:一般用于类的设计。
分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这时就把还有的事物定义成内部类来描述。
如果内部类是静态的,相当于一个外部类
如果内部类中定义了静态成员,内部类必须为静态
为什么内部类能直接访问外部类中的成员呢?
那是因为内部类持有了外部类的引用。外部类名.this
代码示例:
class Outer{
int num = 3;
class Inner{
int num = 4;
void show(){
int num = 5;
System.out.println(Outer.this.num);
}
}
void method(){
new Inner().show();
}
}
(5)匿名内部类:就是内部类的简写格式
*必须有前提:
匿名内部类必须继承或者实现一个外部类或者接口。
*格式:new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容)}
*匿名内部类:其实就是一个匿名子类对象。
简单理解:就是建立一个带内容的外部类或者接口的子类匿名对象。
*什么时候使用匿名内部类呢?
通常在使用方法是接口类型参数,并该接口中的方法不超过三个时,可以将匿名内部类作为参数传递,增强阅读性。