继承和多态
继承的特点:
1.继承具有树形结构,越顶层的越模糊越通用,越底层的越具体越个性
2.子类只能直接继承一个父类,但由于树形结构的存在,一个父亲可以有多个儿子,一个儿子只能有一个父亲
3.树形结构的顺序,兔子是食草动物是正确的,但食草动物是兔子是不正确的。(is-a)
继承的好处:
-
减少代码量
-
方便代码修改
继承的使用:
-
java只支持单一继承,即一个父类可以有多个孩子,一个孩子只能继承一个父类。
-
java中经常出现多层继承。C继承B,B继承A。
-
子类可以继承父类中使用public和protected修饰的属性和方法,不论子类和父类是否在同一包中。
-
子类可以继承父类中使用默认修饰符修饰的属性和方法,但子类和父类必须在同一个包中。
-
子类无法继承父类中使用private修饰的属性和方法。但可以通过继承它的getter/setter方法访问到私有属性。
-
子类无法继承父类的构造方法。
继承中的方法
对于方法而言,要么直接继承原样使用,要么重写父类同名方法。(方法重写也叫做方法覆盖)
方法重写的规则
1.子类的方法必须和父类中被重写的方法的名称相同。
2.子类的方法必须和父类中被重写的方法的参数相同,包括参数的个数、数据类型以及顺序。
3.子类方法的返回类型必须和父类中被重写的方法的返回类型相同或是其子类。
4.子类方法的访问修饰符权限不能小于父类中被重写的方法的访问修饰符权限。
Super关键字
在子类中可以通过super关键字访问父类中的非私有成员。
属性:super.name;
构造方法:super(),super(参数列表);
普通方法:super.show();
继承中的构造方法
父类属性→→父类构造方法→→子类属性→→子类构造方法
继承关系中构造方法的调用规则如下:
如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,写不写“super();”语句,效果是一样的。
多态
1.使用多态的原因:
使用多态可以避免频繁修改代码问题,提高代码的扩展性和可维护性。
2.多态的实质:
同一个引用类型(父类),使用不同的实例对象(子类),从而执行不同的操作(方法重写)。 父类 对象名 = new子类();
-
向上向下转型
向上转型:父类 对象名 = new子类(),符合继承中的is-a关系//不能调用子类独有的成员,因为在执行前无法判断父类所引用对象的实际类型。
向下转型:子类 对象名 = new父类(),向下转型必须强转。因为不符合继承中的is-a关系//可以调用子类独有的方法
-
多态的实现
实现多态的三个步骤:1.实现继承2.子类重写父类方法3.使用父类类型引用的所有子类对象
-
多态细节
成员变量(非私有):
-
编译时:看的是引用类型变量所属的类中是否有所调用的变量
-
运行时:也是看引用类型变量所属的类中是否有所调用的变量
-
成员变量无论编译还是运行都看引用类型变量所属的类
简单记:成员变量在编译和运行时都看等号左边
-
成员方法(非私有):
a)编译时:要查看引用变量所属的类中是否有所调用的成员(不能是独有的方法)。
b)在运行时:要查看对象所属的类中是否有所调用的成员。如果父子出现同名的方法,会运行子类中的方法,因为方法
有覆盖的特性
编译看左边运行看右边
class Animal
{
private int age;
String name;
public Animal()
{
}
public Animal(String name)
{
this.name = name;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
public void eat()
{
System.out.println("动物在吃东西");
}
public void run()
{
System.out.println("动物在跑");
}
}
class Dog extends Animal
{
int age;
public Dog()
{
}
public Dog(String name,int age)
{
super(name);
this.age=age;
}
public int getAge()
{
return age;
}
public void eat()
{
System.out.println("狗在吃东西");
}
public void run()
{
System.out.println("狗在跑");
}
}
class TestExtends
{
public static void main(String[] args)
{
Dog d = new Dog("dog3",9);
//d.setName("dog1");
//d.name="dog1";
System.out.println(d.getName());
//d.setAge(10);
//d.age = 10;//TestExtends.java:38: 错误: age可以在Animal中访问private
System.out.println(d.getAge());
d.eat();
d.run();
}
}