面向对象语言的三大特性:封装、继承、多态。下面简单讲解java这三大对象的概念:
封装:java中通过定义类,把属性,方法封装进类中,通过类只有希望用户访问的功能用户才能调用。
继承:java中通过子类继承父类,子类可以继承父类功能。
多态:java中父类指向子类,通过动态绑定父类实例可以调用子类重写父类的功能。
刚上大学自学C++时讲述面向对象特征时就会列举这三个概念,java语言也不例外。
(1)多态性概念
多态指程序中一个实例变量倒底会指向哪个实现类的引用和该实例中的方法到底指向哪个实现类中的方法,只有在程序运行期间才能决定。所以可以实现不用修改源代码,可以让对象指向不同实现类,随着指向不同实现类程序运行时可以根据具体情形调用同一函数实现不同功能,就是多态性。
简单说:内存中引用到底指向哪个方法在运行时才能决定。
(2)java多态实现原理
多态性实现条件继承,重写,向上转型。
静态绑定&动态绑定:
面向对象语言,多态分为编译时多态和运行时多态。
编译时多态是静态的,主要是指方法的重载,编辑之后会变成两个不同的函数,运行时通过不同的参数类型或个数进行区分。
运行时多态是动态的,它是通过方法的重写来实现的。
java继承口头禅:
成员变量,静态方法看左边;
非静态方法:编译看左边,运行看右边。
解释:当父类变量引用子类对象时,父类变量的成员变量和静态方法与父类是一致的,非静态方法,在编译时是与父类一致的,运行时却与子类一致(重写)。
注意:java中父类中属性只能被隐藏,而不能被覆盖;而对于方法,如果父类和子类存在相同的静态方法,父类中的静态方法会被隐藏。java中final类或方法不能被继承和重写,所以也不存在多态性,java中普通方法继承时可以被重写。
向上转型&向下转型(强制类型转换):
向上转型(子类转成父类):
java中父类实例可以指向子类引用,此时父类实例只能访问父类中定义的属性和方法,子类中存在而父类中不存在的方法,该实例不能访问。子类如果重写了父类中的某些方法,父类实例调用时使用的是子类中的方法。
注意:向上转型是类型安全的,因为父类中的方法在子类中都存在(java中子类继承父类,重写某些方法,访问修饰符权限不能缩小)。向上转型还将导致子类特有属性方法的缺失(无法调用)。
向下转型(父类引用转子类):
父类引用强转成子类实例,向下转型是类型不安全的,转型过程中会进行检查,如果转型失败会报ClassCastException错误。
(3)多态实现方式
多态有很多经典的例子:动物,形状等,下面以动物为例。
3.1 继承和重写实现多态
public class Animal {
public String Tag = "AnimalTag";
public static String sTag = "SAnimalTag";
public static String getSMethod() {
return "SAMethod";
}
public String getData() {
return "AnimalData";
}
}
public class Dog extends Animal{
public String Tag = "DogAnimalTag";
public static String sTag = "DogSAnimalTag";
public static String getSMethod() {
return "DogSAMethod";
}
@Override
public String getData() {
return "DogData";
}
}
public class Cat extends Animal{
public String Tag = "CatAnimalTag";
public static String sTag = "CatSAnimalTag";
public static String getSMethod() {
return "CatSAMethod";
}
@Override
public String getData() {
return "CatData";
}
}
public static void main(String[] args) {
Animal dog = new Dog();
System.out.println(dog.Tag);
System.out.println(dog.sTag);
System.out.println(dog.getSMethod());
System.out.println(dog.getData());
System.out.println("========================");
Animal cat = new Cat();
System.out.println(cat.Tag);
System.out.println(cat.sTag);
System.out.println(cat.getSMethod());
System.out.println(cat.getData());
System.out.println("========================");
Dog dog2 = (Dog) dog;
System.out.println(dog2.Tag);
System.out.println(dog2.sTag);
System.out.println(dog2.getSMethod());
System.out.println(dog2.getData());
System.out.println("========================");
Cat cat2 = (Cat) dog;
System.out.println(cat2.Tag);
System.out.println(cat2.sTag);
System.out.println(cat2.getSMethod());
System.out.println(cat2.getData());
}
result:
AnimalTag
SAnimalTag
SAMethod
DogData
========================
AnimalTag
SAnimalTag
SAMethod
CatData
========================
DogAnimalTag
DogSAnimalTag
DogSAMethod
DogData
========================
Exception in thread "main" java.lang.ClassCastException: com.ldx.extend.Dog cannot be cast to com.ldx.extend.Cat
at com.ldx.extend.Test.main(Test.java:30)
结论:属性,静态方法指向左边,重写的方法最终指向右边。
3.2接口实现多态
多个类实现接口中未实现的方法,然后接口实例指向具体实现类的引用,调用同一函数实现不同功能。
public interface Shape {
public String zone() ;
}
public class Circle implements Shape{
@Override
public String zone() {
return "Circle";
}
}