【Java学习笔记】继承和多态
作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/
1.基本语法:
public class Sub extends Base{
}
当Sub和Base在同一个package时,Sub继承了Base中的public、protected和默认(即未指定访问级别)访问级别的成员变量和方法。
当Sub和Base在不同package时,Sub继承了Base中的public、protected访问级别的成员变量和方法。
2.Java不支持多重继承,但可以通过串行的间接继承进行多重继承
3.所有Java类都直接或间接的集成了java.lang.object类。Object类定义了Java对象具有的相同行为。
4.重载overload
同一个类中,相同名字的方法,但是参数类型、个数或者顺序至少有一项不同。
5.覆盖override
子类覆盖了父类的方法,子类方法的名字、参数签名、返回类型必须与父类相同。若想怪边返回类型等,但是还想用同一个名字,则可以使用先覆盖再重载的策略:
public class Base{
public void method(){
}
}
public class Sub extends Base{
public void method(){//覆盖Base类的method方法
}
public int method(int a){//重载Sub类的method方法
}
}
注意:
a.子类方法不能缩小父类方法的访问权限(可以扩大),而且子类不能抛出比父类方法更多的异常,其必须抛出和父类方法抛出的相同的异常,或者子类方法抛出的异常类是父类方法抛出的异常类的子类。
b.父类的静态方法不能被子类覆盖为非静态方法。同样,父类的非静态方法不能被子类覆盖为静态方法。
c.子类可以定义与父类的静态方法同名的静态方法,以便在父类中隐藏父类的静态方法。子类覆盖静态方法和覆盖一般方法的区别是,运行时,JVM把静态方法和所属类绑定,而将一般方法和所属实例绑定。
d.父类的私有方法不能被子类覆盖。虽然不会出现编译错误,但是实际上子类并没有从父类继承这个方法,所以,其并没有覆盖关系。
e.父类的抽象方法通过子类实现父类的抽象方法或者子类重新声明父类的抽象方法来实现覆盖。
f.父类的非抽象方法可以被覆盖为抽象方法。
6.super关键字
super和this的功能都是使被屏蔽的方法或变量变为可见。不能在静态方法或者静态代码块内不能使用super关键字。
7.多态
实质:指当系统A访问系统B的服务时,系统B可以通过多种实现方式来提供服务,而这一切对系统A是透明的。例如:
public class Feeder{
public void feed(Animal animal,Food food){
animal.eat(food);
}
}
Feeder feeder=new Feeder();
Animal animal=new Dog();
Food food = new Bone();
feeder.feed(animal,food);//喂狗骨头吃
animal=new Cat();
food = new Fish();
feeder.feed(animal,food);//喂猫鱼吃
注意animal被定义为Animal类型,但是有可能引用Dog或Cat类型,在调用animal.eat的时候,JVM会执行animal变量所引用的实例的eat方法。
需要注意的是:
1)静态绑定:对于一个引用类型的变量,Java编译器按照它声明的类型来处理。例如,Base who = new Sub();
这个who是Base类型的引用变量,Java编译器就会按照Base类型来处理。要访问Sub类的成员,则使用强制类型转换:((sub)who).subVar="123";
这适用于成员变量(包括静态变量和实例变量),静态方法
2)动态绑定:对于一个引用类型的变量,运行时JVM按照其实际引用的对象的方法进行绑定。实例方法就属于这一类。
3)Java允许在具有直接或间接的继承关系的类之间进行类型转换,对于向上转型,不必使用强制类型转换。
继承的利弊:
提高代码可重用性,是提高系统扩展性的有效手段。但是继承树若是异常复杂,或被随意扩展,反而会削弱系统的可扩展性和可维护性。继承的最大弱点是打破了封装,削弱了子类的独立性。
继承的原则:
1)不考虑Object,继承树应该尽量保持在两到三层。
2)当一个系统使用一棵继承树上的类时,应该尽可能地把引用变量声明为继承树的上层类型。
3)若继承树上有接口类型,那么应该尽可能地把引用变量声明为继承树上层的接口类型。
4)上层完成那些适用于所有子类或大多数子类的方法,否则则设定为抽象方法。
5)在设计继承类的时候,尽可能的封装父类的实现细节,也就是把代表实现细节的属性和方法定义为private类型,若某些实现细节必须被子类访问则设为protected类型。
6)将不允许子类覆盖的方法定义为final类型。
7)父类的构造方法中不要调用可以被子类覆盖的方法。
8)某些类不是为了继承而设计的,那么采用将类声明为final类型,或者将这个类的所有构造方法声明为private类型,然后通过一些静态方法来负责构造自身的实例的两种方法禁止继承。
9)对于一棵设计合理的继承树,子类之间会具有不同的属性和行为。
10)组合关系指的是:类A中包含有类C的属性,则类A称为包装类(整体类),而类C称作被包装类(局部类)。在开发中,组合关系虽然不比继承关系减少代码量,但是维护起来,有更好的松耦合性。不使用继承,而是在类中加入要继承的类的一个实例成员就是组合。继承关系是静态的,在运行时,子类无法改变它的弗雷,但组合关系在运行时可以根据需要改变实现方式。在继承关系中,子类只能继承父类的接口,不能取消父类的方法,但是除非覆盖该方法,并直接抛出java.lang.UnsupportedOperationExcepetion。而组合则不会自动去继承父类的方法。