一、抽象(abstract)类

抽象类,说白了就是包含抽象方法的类。那什么是抽象方法?抽象方法是一种特殊的方法:抽象方法只有声明,而没有具体的实现。抽象方法说白了就是只有方法的声明,没有方法体。

抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。

上图Cat必须实现抽象方法run(),如果不实现,编译通不过。可以选择实现run()方法或者定义Cat为抽象类。

完整截图:

1. 为什么需要抽象类?如何定义抽象类?

  • 是一种模版模式。抽象类为所有子类提供了一个通用模板。子类可以在这个模版基础上进行扩展
  • 通过抽象类,可以避免子类设计的随意性。通过抽象类,我们可以做到严格限制子类的设计,使子类之间更加通用。

2. 抽象类要点

  1. 有抽象方法的类只能定义为抽象类;只要包含一个抽象方法的抽象类,该类必须要定义为抽象类,不管是否还包含其他方法;
  2. 抽象类中可以包含普通方法(有具体实现的方法),当然也可以不包含抽象方法;
  3. 抽象类不能被实例化,即不能用new来实例化抽象类;
  4. 抽象类可以包含属性、方法、构造方法。但是构造方法不能用new来实例,只能用来被子类调用;
  5. 抽象类只能用来被继承;
  6. 抽象方法必须被子类实现,即由子类来进行重写。(不实现的话,编译器会报错)

【示例】

下面通过一下的小程序深入理解抽象类

  因此在类Animal里面只需要定义这个enjoy()方法就可以了,使用abstract关键字把enjoy()方法定义成一个抽象方法,定义如下:public abstract void enjoy();

  从某种意义上来说,抽象方法就是被用来重写的,所以在父类声明的抽象方法一定要在子类里面重写。如果真的不想在子类里面重写这个方法,那么可以再在子类里面把这个方法再定义为抽象方法,因为子类觉得我去实现也不合适,应该让继承我的子类去实现比较合适,因此也可以在继承这个子类的下一个子类里面重写在父类里面声明的抽象方法,这是可以的。

  这里有一个规则:既然父类里面的方法是抽象的,那么对于整个类来说,它就有一个没有实现的方法,这个方法不知道怎么去实现,那么这个类是就是残缺不全的,因此这个类应该被定义为一个抽象类。所以前面这样声明的声明的class Animal应该要在class的前面加上abstract,即声明成这样:abstract class Animal,这样Animal类就成了一个抽象类了。Animal类的最终定义代码如下:

/*** 父类Animal* 在class的前面加上abstract,即声明成这样:abstract class Animal* 这样Animal类就成了一个抽象类了*/
abstract class Animal {public String name;public Animal(String name) {this.name = name;}/*** 抽象方法* 这里只有方法的定义,没有方法的实现。*/public abstract void enjoy(); }

 Java语言规定,当一个类里面有抽象方法的时候,这个类必须被声明为抽象类。

  子类继承父类时,如果这个父类里面有抽象方法,并且子类觉得可以去实现父类的所有抽象方法,那么子类必须去实现父类的所有抽象方法,如:

 1 /**
 2  * 子类Dog继承抽象类Animal,并且实现了抽象方法enjoy
 3  * @author gacl
 4  *
 5  */
 6 class Dog extends Animal {
 7     /**
 8      * Dog类添加自己特有的属性
 9      */
10     public String furColor;
11
12     public Dog(String n, String c) {
13         super(n);//调用父类Animal的构造方法
14         this.furColor = c;
15     }
16
17     @Override
18     public void enjoy() {
19         System.out.println("狗叫....");
20     }
21
22 }

这个父类里面的抽象方法,子类如果觉得实现不了,那么把就子类也声明成一个抽象类,如:

 1 /**
 2  * 这里的子类Cat从抽象类Animal继承下来,自然也继承了Animal类里面声明的抽象方法enjoy(),
 3  * 但子类Cat觉得自己去实现这个enjoy()方法也不合适,因此它把它自己也声明成一个抽象的类,
 4  * 那么,谁去实现这个抽象的enjoy方法,谁继承了子类,那谁就去实现这个抽象方法enjoy()。
 5  * @author gacl
 6  *
 7  */
 8 abstract class Cat extends Animal {
 9
10     /**
11      * Cat添加自己独有的属性
12      */
13     public String eyeColor;
14
15     public Cat(String n, String c) {
16         super(n);//调用父类Animal的构造方法
17         this.eyeColor = c;
18     }
19 }

这里的子类Cat从抽象类Animal继承下来,自然也继承了Animal类里面声明的抽象方法enjoy(),但子类Cat觉得自己去实现这个enjoy()方法也不合适,因此它把它自己也声明成一个抽象的类,那么,谁去实现这个抽象的enjoy方法,谁继承了子类,那谁就去实现这个抽象方法enjoy()。如:

 1 /**
 2  * 子类BlueCat继承抽象类Cat,并且实现了从父类Cat继承下来的抽象方法enjoy
 3  * @author gacl
 4  *
 5  */
 6 class BlueCat extends Cat {
 7
 8     public BlueCat(String n, String c) {
 9         super(n, c);
10     }
11
12     /**
13      * 实现了抽象方法enjoy
14      */
15     @Override
16     public void enjoy() {
17         System.out.println("蓝猫叫...");
18     }
19
20 }

完整的测试代码如下:

  1 package javastudy.summary;
  2
  3 /**
  4  * 父类Animal
  5  * 在class的前面加上abstract,即声明成这样:abstract class Animal
  6  * 这样Animal类就成了一个抽象类了
  7  */
  8 abstract class Animal {
  9
 10     public String name;
 11
 12     public Animal(String name) {
 13         this.name = name;
 14     }
 15
 16     /**
 17      * 抽象方法
 18      * 这里只有方法的定义,没有方法的实现。
 19      */
 20     public abstract void enjoy();
 21
 22 }
 23
 24 /**
 25  * 这里的子类Cat从抽象类Animal继承下来,自然也继承了Animal类里面声明的抽象方法enjoy(),
 26  * 但子类Cat觉得自己去实现这个enjoy()方法也不合适,因此它把它自己也声明成一个抽象的类,
 27  * 那么,谁去实现这个抽象的enjoy方法,谁继承了子类,那谁就去实现这个抽象方法enjoy()。
 28  * @author gacl
 29  *
 30  */
 31 abstract class Cat extends Animal {
 32
 33     /**
 34      * Cat添加自己独有的属性
 35      */
 36     public String eyeColor;
 37
 38     public Cat(String n, String c) {
 39         super(n);//调用父类Animal的构造方法
 40         this.eyeColor = c;
 41     }
 42 }
 43
 44 /**
 45  * 子类BlueCat继承抽象类Cat,并且实现了从父类Cat继承下来的抽象方法enjoy
 46  * @author gacl
 47  *
 48  */
 49 class BlueCat extends Cat {
 50
 51     public BlueCat(String n, String c) {
 52         super(n, c);
 53     }
 54
 55     /**
 56      * 实现了抽象方法enjoy
 57      */
 58     @Override
 59     public void enjoy() {
 60         System.out.println("蓝猫叫...");
 61     }
 62
 63 }
 64
 65 /**
 66  * 子类Dog继承抽象类Animal,并且实现了抽象方法enjoy
 67  * @author gacl
 68  *
 69  */
 70 class Dog extends Animal {
 71     /**
 72      * Dog类添加自己特有的属性
 73      */
 74     public String furColor;
 75
 76     public Dog(String n, String c) {
 77         super(n);//调用父类Animal的构造方法
 78         this.furColor = c;
 79     }
 80
 81     @Override
 82     public void enjoy() {
 83         System.out.println("狗叫....");
 84     }
 85
 86 }
 87
 88 public class TestAbstract {
 89
 90     /**
 91      * @param args
 92      */
 93     public static void main(String[] args) {
 94
 95         /**
 96          * 把Cat类声明成一个抽象类以后,就不能再对Cat类进行实例化了,
 97          * 因为抽象类是残缺不全的,缺胳膊少腿的,因此抽象类不能被实例化。
 98          */
 99         //Cat c = new Cat("Catname","blue");
100         Dog d = new Dog("dogname","black");
101         d.enjoy();//调用自己实现了的enjoy方法
102
103         BlueCat c = new BlueCat("BlueCatname","blue");
104         c.enjoy();//调用自己实现了的enjoy方法
105     }
106 }

View Code

二、接口(interface)

接口,比抽象类还要抽象的类。

如:接口MyInterface

实现类:MyClass

1. 为什么需要接口?接口和抽象类的区别?

  • 接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了“规范和具体实现的分离。
  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是……则必须能……”的思想。(如果你是天使,则必须能飞,如果你是汽车,则必须能跑……)
  • 接口的本质是契约,就像我们人间的法律一样,制定好后大家都遵守。
  • 项目的具体需求多变,我们必须以不变应万变才能从容开发,此处的不变就是规范。因此,我们开发项目往往都是面向接口编程!

2. 如何定义接口?

格式:

3. 接口要点

  1. 子类通过implements来实现接口中的规范;
  2. 接口不能创建实例,但是可以用于声明引用变量类型;
  3. 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public;
  4. 接口支持多继承
  5. 接口和接口之间可以相互继承,类和类之间可以相互继承,类和接口之间,只能是类来实现接口

   JAVA是只支持单继承的,但现实之中存在多重继承这种现象,如“金丝猴是一种动物”,金丝猴从动物这个类继承,同时“金丝猴是一种值钱的东西”,金丝猴从“值钱的东西”这个类继承,同时“金丝猴是一种应该受到保护的东西”,金丝猴从“应该受到保护的东西”这个类继承。这样金丝猴可以同时从 “动物类”、“值钱的东西类”、“应该受到保护的东西” 这三个类继承,但由于JAVA只支持单继承,因此金丝猴只能从这三个类中的一个来继承,不能同时继承这三个类。因此为了封装现实生活中存在的多重继承现象,为了实现多继承,可以把其中的两个类封装成接口。使用接口可以帮助我们实现多重继承。

  接口(interface)是一种特殊的抽象类,在这种抽象类里面,所有的方法都是抽象方法,并且这个抽象类的属性(即成员变量)都是声明成“public static final 类型 属性名”这样的,默认也是声明成“public static final”即里面的成员变量都是公共的、静态的,不能改变的。因此在接口里面声明常量的时候,可以写成“public static final 类型 常量名=value(值)”这样的形式,也可以直接写成“类型 常量名=value(值)如:“public static final int id=10”可以直接写成“int id=10”这样的形式,因为在接口里面默认的属性声明都是“public static final”的,因此“public static final”可以省略不写。在接口里面声明的抽象方法可以不写abstract关键字来标识,因为接口里面所有的方法都是抽象的,因此这个“abstract”关键字默认都是省略掉的,如在一个接口里面声明这样的三个方法:“public void start()”、“public void run()”、“public void stop()”这三个方法前面都没有使用abstract关键字来标识,可它们就是抽象方法,因为在接口里面的声明的方法都是抽象方法因此在接口里面的抽象方法都会把abstract关键字省略掉,因为默认声明的方法都是抽象的,所以就没有必要再写“abstract”字了,这一点与在抽象类里面声明抽象方法时有所区别,在抽象类里面声明抽象方法是一定要使用“abstract”关键字的,而在接口里面声明抽象方法可以省略掉“abstract。注意:在接口里面声明的抽象方法默认是“public(公共的)”的,也只能是“public(公共的)”之所以要这样声明是为了修正C++里面多重继承的时候容易出现问题的地方,C++的多继承容易出现问题,问题在于多继承的多个父类之间如果他们有相同的成员变量的时候,这个引用起来会相当地麻烦,并且运行的时候会产生各种各样的问题。JAVA为了修正这个问题,把接口里面所有的成员变量全都改成static final,成员变量是static类型,那么这个成员变量就是属于整个类里面的,而不是专属于某个对象。对于多重继承来说,在一个子类对象里面实际上包含有多个父类对象,而对于单继承来说,子类对象里面就只有一个父类对象。多继承子类对象就有多个父类对象,而这些父类对象之间可能又会存在有重复的成员变量,这就非常容易出现问题,因此在JAVA里面避免了这种问题的出现,采用了接口这种方式来实现多继承。作为接口来说,一个类可以从接口继承(或者叫实现接口),这也是多继承,接口里面的成员变量不专属于某个对象,都是静态的成员变量,是属于整个类的,因此一个类去实现多个接口也是无所谓的,不会存在对象之间互相冲突的问题。实现多个接口,也就实现了多重继承,而且又避免了多重继承容易出现问题的地方,这就是用接口实现多重继承的好处。

参数

抽象类

接口

默认的方法实现

它可以有默认的方法实现

接口完全是抽象的。它根本不存在方法的实现

实现

子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。

子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现

构造器

抽象类可以有构造器

接口不能有构造器

与正常Java类的区别

除了你不能实例化抽象类之外,它和普通Java类没有任何区别

接口是完全不同的类型

访问修饰符

抽象方法可以有publicprotecteddefault这些修饰符

接口方法默认修饰符是public。你不可以使用其它修饰符。

main方法

抽象方法可以有main方法并且我们可以运行它

接口没有main方法,因此我们不能运行它。

多继承

抽象方法可以继承一个类和实现多个接口

接口只可以继承一个或多个其它接口

速度

它比接口速度要快

接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。

添加新方法

如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。

如果你往接口中添加方法,那么你必须改变实现该接口的类。


相关链接:

java基础学习总结——抽象类

java基础学习总结——接口

转载于:https://www.cnblogs.com/Qian123/p/5190539.html

面向对象编程(十五)——抽象类和接口相关推荐

  1. Java第五次作业--面向对象高级特性(抽象类和接口)

    一.学习要点 认真看书并查阅相关资料,掌握以下内容: 掌握抽象类的设计 掌握接口的设计 理解简单工厂设计模式 理解抽象类和接口的区别 掌握包装类的应用 掌握对象的比较方法和比较器的使用 学习使用日期操 ...

  2. 面向对象编程(七):接口(抽象类)

    C++ 接口(抽象类) 接口描述了类的行为和功能,而不需要完成类的特定实现. C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念. 如果类中至 ...

  3. 面向对象编程(十二)——final关键字

    阅读目录 final关键字 final修饰变量 final修饰方法 final修饰类 Final && Static 总结 final关键字 Java关键字final有"这是 ...

  4. Java面向对象那些事之抽象类、接口

    目录 前言 一.抽象类 1.抽象类概述 2. 抽象类特点 3.抽象类成员特点 4.抽象类案例 二.接口 1.接口概述 2.接口特点 3.接口成员特点 4.接口案例 5.类和接口的关系 6.抽象类和接口 ...

  5. C语言面向对象编程(五):单链表实现

    前面我们介绍了如何在 C 语言中引入面向对象语言的一些特性来进行面向对象编程,从本篇开始,我们使用前面提到的技巧,陆续实现几个例子,最后呢,会提供一个基本的 http server 实现(使用 lib ...

  6. 类的成员包含 java_Java 面向对象(十五)类的成员 之 内部类

    一.内部类 1.引入 类的成员包括: (1)属性:成员变量: (2)方法:成员方法: (3)构造器: (4)代码块: (5)内部类: 其中1.2是代表这类事物的特征: 其中3.4是初始化类和对象用的: ...

  7. Java面向对象(3) —— 抽象类、接口、内部类、匿名内部类

    目录 抽象类(abstract) 抽象类的使用方法 抽象类的应用:模板方法模式 接口 接口的概念 接口的特点 接口的使用 接口实现与抽象类继承的区别 接口的多继承 内部类 概念 成员内部类(使用较多) ...

  8. 面向对象编程(五):数据抽象

    C++ 数据抽象 数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节. 数据抽象是一种依赖于接口和实现分离的编程(设计)技术. 让我们举一个现实生活中的真实例子 ...

  9. java学习笔记(十)—— 抽象类、接口、内部类

    在之前的学习中,父类其实就是子类的抽象了,比如老虎和兔子都可以被抽象成动物.抽象类是更进一步的抽象,而接口是在抽象类的基础上又抽象了一层. 一.抽象类和抽象方法 1.抽象方法只有方法名,没有方法体. ...

最新文章

  1. what courses to choose at Cambridge?
  2. 59 MM配置-后勤发票校验-维护税代码缺省值
  3. c语言输入成绩求不及格,输入一个学生信息,可以输出,不及格那个输出狗后会有程序停止运行...
  4. excel如何把顺序倒过来_春节酒局多,这些葡萄酒倒酒礼仪你一定要知道
  5. 一份完整的建模文档需涵盖的模块与指标
  6. [转]python中去掉字符串中的\xa0、\t、\n
  7. C#开发高亮语法编辑器(一)——TextBox ,RichTextBox的局限性
  8. 设计模式---代理模式(c++实现)
  9. homestead安装swoole扩展
  10. 最长回文子串-----Manacher算法
  11. 面试官:Glide 是如何加载 GIF 动图的?
  12. 云计算基础与应用 - 云计算架构
  13. excel 第18讲:lookup函数与数组
  14. linux v4l2色调,V4L2下摄像头的详细参数调整
  15. 三星Cortex-A53八核6818核心板
  16. 页面设计如何进行颜色搭配
  17. Cheat sheet FOR Python Packages
  18. 轨迹动画(屏幕线条环绕)
  19. Symbian UIQ简介
  20. Java实现 LeetCode 377 组合总和 Ⅳ

热门文章

  1. 使用pip来安装pyOpenSSL
  2. 分享一个vscode主题收录网站,有了这个网站不用再求别人啦
  3. 学习VUE时,利用webpack打包的错误处理方法
  4. 计算机组成原理考试复习
  5. 公告牌为什么有些是纸质,有些是电子的
  6. unity 草 可以一棵棵种吗?_种黄瓜这几种做法是错误的,却还有好多人在犯
  7. ccf画图java详细解析_ccfjava答案
  8. moto linux手机,moto linux手机目录简解
  9. 钜惠来袭丨神策学堂推出 SACA 四季班,留给你的时间不多了
  10. 获奖公布 | Hello,SDK!数据采集黑客松大赛完美落幕!(含活动预告)