继承与多态
继承;
java中所有类的父类Object
构造方法无法被继承。
方法的覆盖:返回值不同无法构成方法的覆盖。
java中所有类的父类Object
构造方法无法被继承。
方法的覆盖:返回值不同无法构成方法的覆盖。
访问修饰符访问级别:
public>protected>default>private
public>protected>default>private
在覆盖父类的方法时:
子类的覆写方法的修饰符不能低于父类的对应方法的访问修饰符。
如:
public class Animal{
protected void sleep(){
System.out.println("Animal");
}
}
public class Person extends Animal{
private void sleep(){
System.out.println("Person");
}
}
分析:还是按照多态来理解。
假如有这样一个方法
void test(Animal a){
a.sleep();
}
假设编译没问题,对于Animal类型而言,它的sleep方法具有相应的可见性(test方法属于 位于同一个包中的某类)。但如果传给test方法的是Person实例,则根据多态会调用person类的sleep()方法,而该方法却是私有的,无法 调用,这就导致了问题。所以可以反正以上观点。java语言也就规定以上约束。
super关键字 :
在java类中使用super来引用父类的成分
--super可用于访问父类中定义的属性
--super可用于调用父类中定义的成员方法
--super可用于在子类构造器中调用父类的构造器
--super的追溯不仅于直接父类
super()一定放在构造函数的第一行。
构造器 (默认构造器和自定义构造器)
类如果提供了非默认构造函数,则编译器不提供默认构造器,除非在定义类时未指定任何构造器。
如:
在java类中使用super来引用父类的成分
--super可用于访问父类中定义的属性
--super可用于调用父类中定义的成员方法
--super可用于在子类构造器中调用父类的构造器
--super的追溯不仅于直接父类
super()一定放在构造函数的第一行。
构造器 (默认构造器和自定义构造器)
类如果提供了非默认构造函数,则编译器不提供默认构造器,除非在定义类时未指定任何构造器。
如:
public class Base{
public Base(int i){}
}
public class Sub extends Base{
} //该类编译报错,父类没有默认构造器,子类的默认构造器找不到父类的默认构造器
重载:
方法名相同(参数类表不同),只能利用参数类型和参数个数的不同来重写方法。
**方法的覆盖:返回值不同无法构成方法的覆盖。**
证明 为什么重写方法不能依赖返回值的不同。
使用反证法:假如假设成立的话,
父类:
public class Base{
public int test(){
return 1;
}
}
子类:
public class Sub extends Base{
public String test(){
return "test";
}
}
测试:
public class Test{
public static void main(String[] args){
Base b = new Sub();
int i = b.test();
}
}
分析:
假设可以这样写,从语法和语义角度看没有问题。运行时,b虽然声明为Base类型,但它的真正实例为Sub类型。这样根据多态,调用 b.test()应该使用子类的test方法,这样就返回一个String,这样程序便会出现转换异常,所以这样写会导致程序的不安全性,所以假设不成 立,问题得证。
进一步的补充:
父类:
public class Base {
public Object test(){
return "base";
}
}
子类:
public class Sub extends Base{
public String test(){
return "sub";
}
}
测试:
Base o = new Sub();
System.out.println(o.test());
打印输出:
sub
分析:子类覆盖的方法的返回值是父类该方法的extension,这样在多态情况下没有问题。也能实现覆盖了。所以上面的方法返回值的约束可以做点修正哈。