{Java初级系列四}---继承、接口和抽象类

本人为自学Java系列,内容来自于中国大学mooc华东师范大学陈育良教授《Java核心技术》,在此感谢老师!

一:继承

  • 面向对象和面向过程编程语言最大的特点就是变量类型的继承,通过extend去继承父类
  • 继承能够解决很多类型的重复定义,类别内的对象属性和方法都具有一定的共同点。将共同点提取出来,即形成父类/基类/超类—Parent class/Base class/Super class
  • 其他类型则自动生成子类/派生类-----Child class/Derived class

    Human类把Man和Woman的height、weight成员属性和eat方法写成一个父类,两个子类就能继承Human,从而节约很多重复定义。

     

  • 子类会继承父类所有的属性和方法,但是不能访问private成员。
  • 子类会继承父类的父类所有的属性和方法,但是不能访问private成员
  • 单根继承原则:每个类都只能继承一个类,如果不写extends,Java类都默认继承java.lang.object,Objecvt里面默认有clone equlas finalize getcalss hashCode toString等方法
  • 同样方法名和参数情况下,本类的方法会比父类的方法优先级更高

父类:

  1. public class Base {  
  2.  private int num = 10;  
  3.   public int getNum() {  
  4.       return this.num;  
  5.   }  
  6. }  

子类:

  1. public class Derived extends Base{  
  2.     private int num = 20;     
  3.         
  4.     public int getNum() {  
  5.         return this.num;  
  6.     }     
  7.         
  8.     public static void main(String[] args) {  
  9.         Derived foo = new Derived();  
  10.         System.out.println(foo.getNum());  
  11.     }  
  12. }  

程序返回值为20。子程序会选择本类的方法进行执行。

 

解释下上章节的继承函数

扫描二维码关注公众号,回复: 8983587 查看本文章

  1. public class A {  
  2.  public A() {  
  3.      System.out.println("11111");  
  4.  }  
  5.  public A(int a) {  
  6.      System.out.println("22222");  
  7.  }  
  8. }  

 

  1. public class B extends A {  
  2.  public B() {  
  3.      //super();  
  4.      System.out.println("333333");  
  5.  }  
  6.  public B(int b) {  
  7.      //super(b);  
  8.      System.out.println("444444");  
  9.  }  
  10.     public static void main(String[] args) {  
  11.         // TODO Auto-generated method stub  
  12.          B obj = new B();  
  13.          System.out.println("==========");  
  14.          B obj1 = new B(10);  
  15.     }  
  16.     
  17. }  

输出结果:

  1. 11111  
  2. 333333  
  3. ==========  
  4. 11111  
  5. 444444  

两个构造器都会默认调用父类的无参构造函数,输入11111.

当我们在每个构造器前面加上super函数,而且super语句必须放在第一条。

当去掉第二行super(b)注释,输出值:

  1. 11111  
  2. 333333  
  3. ==========  
  4. 22222  
  5. 444444  

二:抽象类

抽象类:属性+方法组成,完整的类所有的方法都有实现(方法体),一个完整的类才可以被实例化,如果一个类暂时没有方法实现,就定义为抽象类,抽象类是无法被实例化的。

  • 抽象类关键字abstract声明;
  • 抽象类的组成

--optional 成员变量,个数不限

--optional具体方法,方式有实现,个数不限

-- optional 抽象方法,加abstract关键字,个数不限

同时对于抽象类我们还要遵循以下的规则

  • 抽象类也是类,同样要满足单根继承原则。一个类只能继承一个抽象类
  • 完整类要继承抽象类必须实现其所有的方法,否则只能定义为抽象类

抽象类:

  1. public abstract class Shape {  
  2.     int area;  
  3.     public abstract void calArea();  
  4.     
  5. }  

完整类继承于抽象类,并实现抽象类中的方法体。

  1. public class Rectangle extends Shape {  
  2.   int width;  
  3.   int length;  
  4.   public void set(int length, int width) {  
  5.       this.width = width;  
  6.       this.length = length;  
  7.   }  
  8.   public void calArea() {  
  9.       System.out.println(this.length *this.width);  
  10.   }  
  11.     public static void main(String[] args) {  
  12.         // TODO Auto-generated method stub  
  13.          Rectangle obj = new Rectangle();  
  14.          obj.set(10,5);  
  15.          obj.calArea();  
  16.     }  
  17.     
  18. }  

三:接口

  • 紧接继承的定义,如果类的所有方法都没有实现,那么这个类就是接口interface。类只可以继承-extends一个类,但是可以实现-implements多个接口,继承和实现可以同时进行
  • 类可以继承多个接口,没有实现的方法将会叠加,即A继承与B C两个接口,B C两个接口所有方法体将会叠加,如果类没有实现接口所有方法,只能定义为抽象类
  • 接口里可以定义变量,但是一般是常量,详情可以参考final节

    这里给大家写几个简单的例子来描述: 类-抽象类-接口之间的关系

 

定义三个接口:

  1. public interface Aninmal {  
  2.     public void eat();  
  3.     public void move();  
  4. }  

接口2:

  1. public interface ClassTree {  
  2.   public void climb();  
  3. }  

接口3

  1. public interface CatFamliy extends ClassTree, Aninmal {  
  2. // 继承多个接口相当于将没有实现的方法全部叠加  
  3.     // eat()  
  4.     // move()  
  5.     //climb()  
  6. }  

Cat类是实现与Animanl接口的,必须实现它所有的方法体

  1. public class Cat implements Aninmal {  
  2.     public void eat() {  
  3.         System.out.println("Cat can eat");  
  4.     }  
  5.     public void move() {  
  6.         System.out.println("Cat can move");  
  7.     }  
  8. }  

类LandAnimal由于只实现Animal中的move方法,没有实现eat方法,定义为abstract类

  1. public abstract class LandAnimal implements Aninmal {  
  2.     public void move() {  
  3.         System.out.println("LandAnimal cat move");  
  4.             
  5.     }  
  6.     //public abstract void eat();  
  7. }  

Rabbit类是先继承LandAnimal抽象类再实现ClassTree接口

  1. public class Rabbit extends LandAnimal implements ClassTree {  
  2. // 必须先继承再实现  
  3.     public void eat() {  
  4.         System.out.println("Rabbit cat eat");  
  5.     }  
  6.     public void climb () {  
  7.         System.out.println("Rabbit can climb");  
  8.     }  
  9. }  

Tiger类是实现CatFamily接口,所以要实现这个接口所有方法

  1. public class Tiger implements CatFamliy {  
  2.     public void move() {  
  3.         System.out.println("Tiger can move");  
  4.     }  
  5.     public void eat() {  
  6.         System.out.println("Tiger can move");  
  7.     }  
  8.     public void climb() {  
  9.         System.out.println("Tiger can move");  
  10.     }  
  11. }  

四:转型

  1. 基本类型转型

  2. 变量支持相互转化。比如 int a = (int)3.5 这里进行变量的强转换

    基本类型转换:

    从高精度往低精度转化,会损失信息,称为收缩变换。这种情况我们需要声明类型转化

    从低精度往高精度转化,不损失信息,称为宽松变换。这种情况Java会自动转化。

    1. public class Test{  
    2.     public static void main(String[] args) {  
    3.         int  a;  
    4.         a = (int)3.5;  // 收缩变换
    5.         System.out.println(a);  
    6.         double b = 3;  // 宽松变换
    7.         System.out.println(b);  
    8.          }  

    结果:

    1. 3  
    2. 3.0  
  3. 类转型

类型之间可以互相转型,但是只限制于有继承关系的类

---子类可以转化为父类,但是父类不能转化为子类。因为子类有更多的方法和变量

---子类继承父类所有的财产,子类转化为父类(从大到小,即向上转型);从父类直接变成子类(从小变大,即向下转型)

  1. public class Man extends Human {  
  2.     public void eat() {  
  3.         System.out.println("i cat eat more");  
  4.     }  
  5.     public void plough() {  
  6.             
  7.     }  
  8.   public static void main(String[] arsg) {  
  9.       Man obj1 = new Man();  
  10.       obj1.eat();  
  11.       Human obj2 =  new Man();// upcast向上转换  
  12.       obj2.eat();  
  13.         Man obj3 = (Man)obj2;  
  14.         obj3.eat();  
  15. //    Man obj3 = new Human();  Human是父类,Man拥有父类不具有的成员变量与方法。  
  16. //     所以Human对象内存无法转型为Man  
  17.   }  
  18. }  

父类:

package service;

 

public class Human {

int height;

int weight;

public void eat() {

     System.out.println("I cat eat");

}

}

输出结果:

i cat eat more

i cat eat more

i cat eat more

 

如上序程序就有类转型,Man类转为Human类,即衍生类引用转为基类引用。类型转换的作用就是带来多态

程序中有一个eat方法,和父类中的eat方法方法名和参数一致,我们把这个称为方法重写。(不同于重载,重载是方法名一致但是形参类型或者个数不一致)。且子类方法的优先级高于父类。

五:多态

多态拥有三个必要条件:

  1. 继承 extends
  2. 重写 overwrite
  3. 父类引用指向子类对象 Father obj = new Son()

    当我们使用多态调用方法时,对象会检查父类是否有此方法,如果没有就会编译错误。如果有的话,就会调用子类同名方法。

     

    多态的作用到底有什么呢:

    1. 以统一的接口来操纵某一类中不同对象的动态行为
    2. 对象之间的解耦

代码实例:

public interface Aninmal {

public void eat();

public void move();

}

 

 

public class Dog implements Aninmal {

    public void eat() {

        System.out.println("Dog can eat");

    }

public void move() {

        System.out.println("Dog can move");

    }

}

 

 

public class Cat implements Aninmal {

    public void eat() {

        System.out.println("Cat can eat");

    }

public void move() {

        System.out.println("Cat can move");

    }

}

  1. public class AnimalTest {  
  2.   public static  void  haveLunch(Aninmal a) {  
  3.       a.eat();  
  4.   }  
  5.   Aninmal a;  
  6.   AnimalTest c = new AnimalTest();  
  7.   public static void main(String[] args) {  
  8.      haveLunch(new Cat()); // 此处等于转型  Aninaml a = new Cat(); haveLunch(a)  
  9.      haveLunch(new Dog());  
  10.      haveLunch(new Aninmal() {  
  11.             
  12.         @Override  
  13.         public void move() {  
  14.             // TODO Auto-generated method stub  
  15.             System.out.println("move Test");  
  16.         }  
  17.             
  18.         @Override  
  19.         public void eat() {  
  20.             // TODO Auto-generated method stub  
  21.             System.out.println(" eat Test");  
  22.         }  
  23.     });  
  24.   }  
  25. }  

输出结果:

  1. Cat can eat  
  2. Dog can eat  
  3.  eat Test  

 

我们通过Animal接口,完成对于Dog和class两个不同对象的自己各自独有的行为。第三个是匿名类,重写补全Animal接口的方法,调用补全的方法。

我们haveLunch方法形参可以传入不同对象,这个称为对象的解耦。

 

六:契约设计

契约:通过接口定义了方法的名称,参数和返回值。规范了派生类的行为

基于接口,利用转型和多态,不影响真正方法调用,成功地将调用类和被调用类解耦。

  • 被调用类:

  • 调用类:

两个方法之间已经解耦设计,havelunch已经定义其方法名 参数名和方法体,调用类可以利用多态的功能实现多个对象的不同行为方法。

猜你喜欢

转载自www.cnblogs.com/yblecs/p/12272740.html