对象多态性严格来讲现在只能为其讲解基本概念,以及相关使用限制
多态性依赖:方法的覆写
以下的内容只是为了解释多态性的特点,代码本身并没有意义
观察如下程序
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class B extends A{
public void print(){
System.out.println("B.public void print()");
}
}
public class testDemo{
public static void main(String args[]){
B b = new B();
b.print();
}
}
多态性严格来讲有两种描述形式
1.方法的多态性
|-方法的重载:同一个方法名称,根据传入参数的类型及个数不同执行不同的方法体
|-方法的覆写:同一个方法,会根据子类的不同,实现不同的功能
2.对象的多态性:指的是发生在继承关系类之中,子类和父类之间的转换问题
|-向上转型(自动完成):父类 父类对象=子类实例
|-向下转型(强制完成):子类 子类对象=(子类)父类实例
向上转型
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class B extends A{
public void print(){
System.out.println("B.public void print()");
}
}
public class testDemo{
public static void main(String args[]){
A b = new B();
b.print();
}
}
向下转型
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class B extends A{
public void print(){
System.out.println("B.public void print()");
}
}
public class testDemo{
public static void main(String args[]){
A a = new B();
B b = (B) a;
b.print();
}
}
以上的转型操作难道只是为了一个向上和向下的转型处理吗?没有其它意义吗?
由上转型:由于所有的子类对象实例都可以自动的身上转型,所以在于参数的统一上
代码示例
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class B extends A{
public void print(){
System.out.println("B.public void print()");
}
}
class C extends A{
public void print(){
System.out.println("C.public void print()");
}
}
public class testDemo{
public static void main(String args[]){
// 只要是A类的子类都可以使用向上转型,由A类接收
A a1 = new B(); // 向上转型
A a2 = new C(); // 向上转型
a1.print();
a2.print();
}
}
参数统一之后,还可以调用子类覆写后的方法体,即同一个方法针对不同的子类可以有不同的实现
向下转型:指的是父类要调用子类自己特殊的方法,所有的父类发生了向上转型之后只能够看见父类自己定义的全部方法信息,但是看不见子类特殊的方法,于是此时就需要使用向下转型将父类对象转换为子类对象此时就可以使用子类的特殊功能
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class B extends A{
public void print(){
System.out.println("B.public void print()");
}
}
class C extends A{
public void print(){
System.out.println("C.public void print()");
}
public void func(){
System.out.println("C.public void func()");
}
}
public class testDemo{
public static void main(String args[]){
A a2 = new C();
a2.print();
a2.func();
}
}
运行失败,显示找到对应函数
调用扩充的方法
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class B extends A{
public void print(){
System.out.println("B.public void print()");
}
}
class C extends A{
public void print(){
System.out.println("C.public void print()");
}
public void func(){
System.out.println("C.public void func()");
}
}
public class testDemo{
public static void main(String args[]){
A a2 = new C();
C c = (C) a2;
c.print();
c.func();
}
}
运行正常
疑问?以上的代码如果不使用向上转型,而直接使用子类对象进行实例化后也可以直接调用func()方法,为什么还要转型呢?
在之前一直强调,对于数据的操作分为两步:
1.第一步:设置数据(保存数据),最需要的是参数统一功能
2.第二步:取出数据
使用向上现下转型
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class B extends A{
public void print(){
System.out.println("B.public void print()");
}
}
class C extends A{
public void print(){
System.out.println("C.public void print()");
}
public void func(){
System.out.println("C.public void func()");
}
}
public class testDemo{
public static void main(String args[]){
func(new C());
}
public static void func(A a){
//调用个性化特征
C c = (C) a; // 因为要调用子类的特殊功能
c.func();
}
}
对于对象的转型,给出一下的经验总结:
80%的情况下都只会使用向上转型,因为可以得到参数类型的统一,方便于程序设计
子类定义的方法大部分情况下,请以父类的方法名称为标准进行覆写,不要过多的扩充方法
5%的情况下会使用向下转型,目的是调用子类的特殊方法
15%的情况下是不转型,例如:String
个性化的操作在一个标准的开发之中应该少出现,因为对象的转型操作里面毕竟有了强制问题,容易带来安全隐患
观察如下代码
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class C extends A{
public void print(){
System.out.println("C.public void print()");
}
}
public class testDemo{
public static void main(String args[]){
A a = new A();
C c = (C) a;
c.print();
}
}
Exception in thread "main" java.lang.ClassCastException: class A cannot be cast to class C (A and C are in unnamed module of loader 'app')
at testDemo.main(testDemo.java:15)
此时出现的异常表示的是类转换异常,指的是两个没有关系的类对象强制发生转型时所带来的异常,向下转型是不会存在有风险的
为了保证转型的顺序进行,在java里面提供有一个关键字:instanceof
,此关键字的使用:
#对象 instanceof 类
object instanceof Class
如果某个对象是某个类的实例,那么就返回true,否则就返回false
class A{
public void print(){
System.out.println("A.public void print()");
}
}
class C extends A{
public void print(){
System.out.println("C.public void print()");
}
public void func(){
System.out.println("C.public void func()");
}
}
public class testDemo{
public static void main(String args[]){
A a = new A();
A c = new C();
System.out.println(a instanceof A);
System.out.println(a instanceof C);
System.out.println(c instanceof A);
System.out.println(c instanceof C);
if (c instanceof C){ //如果a对象是了类的实例
C cc = (C) c; //向下转型
cc.func();
}
}
}
对于向下转型如果要发生之前,一定要首先发生对象的向上转型,建立关系后才进行。
总结
1.开发之中尽量使用向上转型,以统一参数类型,同时只有发生了向上转型之后才可以发生向下转型
2.子类尽量不要过多的扩充与父类无关的操作方法,90%的情况下子类的方法要与父类的方法保持一致