多态&强制类型转换&抽象类和接口

来源:互联网 发布:网络语音肝是啥意思 编辑:程序博客网 时间:2024/06/09 22:03

多态&强制类型转换&抽象类和接口

1.多态

  • Java引用变量有俩个类型,一个是编译时类型,一个是运行时类型。编译时类型由声明该变量使用类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现多态。
  • 多态存在的三个必要条件:


一,要有继承;
二,要有重写(重写是指子类对父类同一方法的执行代码块重写,而重载是指同一个类下,同一方法名,不同形参的方法);
三,父类引用指向子类对象(左边为父类,右边为子类)。

  • 接下来我们用一个小题目彻底理解多态:

  • (一)相关类:

class A ...{           public String show(D obj)...{                  return ("A and D");           }            public String show(A obj)...{                  return ("A and A");           }   }   class B extends A...{           public String show(B obj)...{                  return ("B and B");           }           public String show(A obj)...{                  return ("B and A");           }   }  class C extends B...{}   class D extends B...{}
  • (二)问题:一下输出结果是什么?
        A a1 = new A();          A a2 = new B();          B b = new B();          C c = new C();           D d = new D();           System.out.println(a1.show(b));   ①          System.out.println(a1.show(c));   ②          System.out.println(a1.show(d));   ③          System.out.println(a2.show(b));   ④          System.out.println(a2.show(c));   ⑤          System.out.println(a2.show(d));   ⑥          System.out.println(b.show(b));    ⑦          System.out.println(b.show(c));    ⑧          System.out.println(b.show(d));    ⑨
  • (三)答案
A and AA and AA and D④   B and A⑤   B and AA and D⑦   B and B⑧   B and B⑨   A and D

在解析答案之前我希望能先讲解一下强制类型转换:

  • 基本数据类型之间强制转换只能在数值类型之间转换,但是数值类型和布尔类型无法进行类型转换。

  • List《String》mlist = new ArrayList<>(); 因为子类是一种特殊的父类,因此Java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,这就是向上转型,向上转型由系统自动完成。 向上转型,运行时会遗忘子类中与父类对象中不同的方法,也会覆盖与父类中相同的方法-重写(方法名,参数都相同)。

  • 子类转父类是向上转型,系统自动完成。父类转子类是向下转型,属于不安全行为,试想,子类中有些方法和成员变量父类没有,如何把没有的东西变为有呢?

  • 对上面答案解析:

  • 第四个输出:子类B实例 new B() 赋给 父类A实例 a2,这是向上转型的结果;这时候a2可以调用:show(D obj),show(A obj),向上转型时子类里不同的方法被遗忘,所以show(B obj)被遗忘;子类会对父类的方法进行重写覆盖。

2.抽象类

-抽象方法:在了解抽象类之前,先来了解一下抽象方法。抽象方法是一种特殊的方法:它只有声明,而没有具体的实现,即没有方法体{ }。抽象方法的声明格式为:

abstract void fun();
  • 抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。

  • 抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。抽象类的构造器不能用于创建实例,主要用于被其子类调用—->我的理解是子类构造器super() 调用父类构造器,为抽象类里面的成员变量赋值。

  • 包含抽象方法的类(1.包括直接定义一个抽象方法;2.或继承一个抽象父类,但没有完全实现其父类的抽象方法;3.或实现了一个借口当没有完全实现接口的抽象方法)只能被定义为抽象类。

  • 如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

  • 包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。

  • 下面介绍一个例子:

建立一个Shape抽象类,代表形状,求面积和周长两个方法建立一个正方形类, 长方形 ,圆类 作为抽象类的子类,通过抽象类来求面积和周长class Test4 {        Shape s;        Test4(Shape s){                this.s = s;        }        public double getTwo(Shape h){                double area = h.getArea();                return 2*area;        }        public static void main(String [] args){                System.out.print("tthellonn");                Shape s1 =new Square(1);                System.out.println("正方形的面积"+s1.getArea());                System.out.println("正方形的周长"+s1.getPan());                Shape s2 = new Rectangle(1,2);                System.out.println("长方形的面积"+s2.getArea());                System.out.println("长方形的周长"+s2.getPan());                Shape s3 = new Circle(1);                System.out.println("圆的面积"+s3.getArea());                System.out.println("圆的周长"+s3.getPan());                Test4 t = new Test4(s1);                System.out.println("正方形面积的两倍"+t.getTwo(s1));                }}abstract class Shape{//抽象类        public abstract double getArea();//抽象方法        public abstract double getPan();}class Square extends Shape{        protected double len;        Square(double len){                this.len = len;        }        public double getArea(){                return len*len;        }        public double getPan(){                return 4*len;        }}class Rectangle extends Square{        private double wid;        Rectangle(double len,double wid){                super(len);                this.wid = wid;        }        public double getArea(){                return wid*len;        }        public double getPan(){                return (wid+len)*2;        }}class Circle extends Shape{        private double r;        Circle (double r){                this.r = r;        }        public double getArea(){                return Math.PI*r*r;        }        public double getPan(){                return Math.PI*r*2;        }}

3.接口

  • 接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。它是对行为的抽象。在Java中,定一个接口的形式如下:
(public) interface interfaceName{}
  • 接口中可以含有 变量和方法。但是要注意,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。

  • 要让一个类遵循某组特地的接口需要使用implements关键字,具体格式如下:

class ClassName implements interface1,interface2...{}

可以看出,允许一个类遵循多个特定的接口。如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。

0 0
原创粉丝点击