码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2020-02-07 14:46:03      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:ima   简单   限制   int   return   转化   情况   叠加   基于   

本人为自学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。子程序会选择本类的方法进行执行。

?

解释下上章节的继承函数

技术图片

  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已经定义其方法名 参数名和方法体,调用类可以利用多态的功能实现多个对象的不同行为方法。

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

标签:ima   简单   限制   int   return   转化   情况   叠加   基于   

原文地址:https://www.cnblogs.com/yblecs/p/12272740.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!