*/

.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}

.hljs-comment,
.hljs-template_comment,
.diff .hljs-header,
.hljs-javadoc {
color: #998;
font-style: italic;
}

.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.javascript .hljs-title,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}

.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #099;
}

.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.tex .hljs-formula {
color: #d14;
}

.hljs-title,
.hljs-id,
.coffeescript .hljs-params,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}

.javascript .hljs-title,
.lisp .hljs-title,
.clojure .hljs-title,
.hljs-subst {
font-weight: normal;
}

.hljs-class .hljs-title,
.haskell .hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}

.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rules .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}

.hljs-attribute,
.hljs-variable,
.lisp .hljs-body {
color: #008080;
}

.hljs-regexp {
color: #009926;
}

.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}

.hljs-built_in,
.lisp .hljs-title,
.clojure .hljs-built_in {
color: #0086b3;
}

.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}

.hljs-deletion {
background: #fdd;
}

.hljs-addition {
background: #dfd;
}

.diff .hljs-change {
background: #0086b3;
}

.hljs-chunk {
color: #aaa;
}

#container {
padding: 15px;
}
pre {
border: 1px solid #ccc;
border-radius: 4px;
display: block;
background-color: #f8f8f8;
}
pre code {
white-space: pre-wrap;
}
.hljs,
code {
font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;
}
:not(pre) > code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
white-space: nowrap;
border-radius: 4px;
}
-->

抽象类(abstract)

  1. 使用abstract关键字来修饰的类是抽象类。使用abstract修饰方法时这个方法称为抽象方法。
  2. 含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被重写。
  3. 抽象类不能被实例化,即不能new该类对象。因为抽象类是比较抽象的类,是残缺不全的类。
  4. 抽象方法只需定义它的结构,不需写方法体。因为抽象方法最终都要被子类重写,即使定义抽象方法也是多余的。
  5. 抽象类中并非一定要包含抽象方法,也并非不能包含普通方法。

以下面多态的示例来说明:

class Animal {
private String name;
Animal(String name) {this.name = name;} public void sing(){System.out.println("animal sing...");} //这是多余的方法
} class Cat extends Animal {
private String eyeColor;
Cat(String n,String c) {super(n); eyeColor = c;} public void sing() {System.out.println("cat sing...");}
} class Dog extends Animal {
private String furColor;
Dog(String n,String c) {super(n); furColor = c;} public void sing() {System.out.println("dog sing...");}
} class Lady {
private String name;
private Animal pet;
Lady(String name,Animal pet) {this.name = name; this.pet = pet;}
public void myPetSing(){pet.sing();}
} public class DuoTai {
public static void main(String args[]){
Cat c = new Cat("catname","blue");
Dog d = new Dog("dogname","black");
Lady l1 = new Lady("l1",c);
Lady l2 = new Lady("l2",d);
l1.myPetSing();
l2.myPetSing();
}
}

父类Animal中的sing()方法迟早要被子类Cat、Dog重写,而且在多态实现下,Animal的sing()完全是多余的。因此,可以将Animal的sing()方法的方法体删掉。

class Animal {
private String name;
Animal(String name) {this.name = name;} public void sing() {}
}

更彻底一点,将sing()方法加上abstract关键字,这个方法变为抽象方法,抽象方法是不完整的方法,它必须被子类重写。抽象方法所在的类也必须加上abstract关键字变成抽象类。成了抽象类后这个类也是不完整的类,所以无法实例化new Animal

abstract class Animal {
private String name;
Animal(String name) {this.name = name;} public abstract void sing();
}

虽然Animal中的sing()用不上了,但它却必须要定义出来,因为它要被子类重写。另外,如果子类不想重写抽象方法,可以将这个子类也定义为抽象类,并让子子类去重写。

接口(interface)

接口定义的是一种具有某种能力的标准,通过接口实现的方式来体现如何具有该这些能力。说白了它就是能实现某些能力的标准。

例如定义一个USB接口的标准,各厂商如何去实现这个标准由各厂商自己去决定,但不管如何,各厂商实现的USB接口必须达到标准所要求具有的能力。

放在编程语言中来说,接口是一种特殊的抽象类,里面的方法必须全部是抽象方法且都是public的,里面的变量也必须都是"public static final"属性的。即使不写这些修饰关键字,默认也是这些属性,但如果写了,就绝对不能写错。

定义接口的方式是使用interface关键字替代class关键字。例如以下定义一个Singable接口,要求必须有喉咙,且能唱歌,能临时停止唱歌。

interface Singable {
public static final boolean houlong = true; public void sing();
public void tmpStop();
}

既然接口是一种抽象类,那么就可以被继承,且里面的方法必须要重写以体现各子类独有的能力。通常接口都被命名为"XXXable",因为接口一般体现的是具有某种能力。

继承接口这个特殊类的术语是"实现接口",使用implement关键字。某个类可以实现多个接口,也就是"多重继承"。不仅如此,实现接口的同时还可以实现extends继承其他类。有以下几种写法:

class A implement intf1 {}
class A implement intf1,intf2 {}
class A extends ParentClass implement intf1,intf2 {}

以下是一个示例,定义了Singable和Paintable两个接口,还定义了两个实现这两接口的类Student和Teacher,它们分别有各自的方法study()和teach()。

interface Singable {
public void sing();
} interface Paintable {
public void paint();
} class Student implements Singable {
private String name;
Student(String name) {this.name = name;} public void study() {System.out.println("Student studing...");} // overwrite methods
public void sing() {System.out.println("Student singing...");}
} class Teacher implements Singable,Paintable {
private String name;
Teacher(String name) {this.name = name;} public void teach() {System.out.println("Teacher teaching...");} // overwrite methods
public void sing() {System.out.println("Teacher singing...");}
public void paint() {System.out.println("Teacher painting...");}
} public class Interface {
public static void main(String[] args) {
Singable s1 = new Student("Malongshuai");
s1.sing();
//s1.study(); //return error! because s1 upcasting from Student to Singable
Student s = (Student)s1;
s.study(); //return true Singable t1 = new Teacher("Gaoxiaofang");
t1.sing();
//t1.paint(); //return error! t1 upcasting from Teacher to Singable,not Paintable
Paintable t = (Paintable)t1;
t.paint();
}
}

上面的示例中,Student类实现了Singable接口,所以它重写了sing(),Teacher类实现了Singable接口和Paintable接口,所以它重写了sing()和paint()。

需要注意的点在于接口和实现接口的类之间具有多态性。正如上面的Singable t1 = new Teacher("Gaoxiaofang");,此时t1虽然引用的是Teacher对象,但它能识别的数据只有Singable接口的成员sing(),而无法识别Teacher自身的方法teach()和Paintable接口的方法paint(),且因为子类Teacher重写了Singable中的sing(),所以多态性使得t1.sing()调用的是Teacher重写后的sing()。要访问paint(),需要将t1转型为Paintable类型或者Teacher类型,要访问teach(),就必须转型为Teacher类型。

注:若您觉得这篇文章还不错请点击右下角推荐,您的支持能激发作者更大的写作热情,非常感谢!

java面向对象基础(四):抽象类和接口的更多相关文章

  1. java基础(四)-----抽象类与接口

    抽象类与接口是java语言中对抽象概念进行定义的两种机制,正是由于他们的存在才赋予java强大的面向对象的能力.他们两者之间对抽象概念的支持有很大的相似,甚至可以互换,但是也有区别. 一.抽象类 我们 ...

  2. java面向对象编程(八)--抽象类、接口

    1.抽象类 1.1抽象类概念 当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法[抽象方法],用abstract来修饰该类[抽象类]. //抽象类的必要性[Demo124.java] ...

  3. 深入java面向对象三:抽象类和接口(转载)

    文章系转载,地址: http://blog.csdn.net/xw13106209/article/details/6923556 1.概述     一个软件设计的好坏,我想很大程度上取决于它的整体架 ...

  4. Java笔记(十四)……抽象类与接口

    抽象类概念 抽象定义: 抽象就是从多个事物中将共性的,本质的内容抽取出来. 例如:狼和狗共性都是犬科,犬科就是抽象出来的概念. 抽象类: Java中可以定义没有方法体的方法,该方法的具体实现由子类完成 ...

  5. Java基础之抽象类与接口

    Java基础之抽象类与接口 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的时候 ...

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

    Java第五次作业--面向对象高级特性(抽象类与接口) (一)学习总结 1.在上周完成的思维导图基础上,补充本周的学习内容,对Java面向对象编程的知识点做一个全面的总结. 2.汽车租赁公司,出租汽车 ...

  7. java基础之抽象类与接口的区别

    在学习java的过程中,或者是在找工作笔试或面试的时候,如果你是java岗位,那么抽象类与接口的区别无疑是一个大热点,是各大公司都想要考的一个小知识点,下面是我为了9月份秋招自己总结的,若有不对的地方 ...

  8. 【重走Android之路】【Java面向对象基础(三)】面向对象思想

    [重走Android之路][基础篇(三)][Java面向对象基础]面向对象思想   1 面向对象的WWH   1.1 What--什么是面向对象         首先,要理解“对象”.在Thinkin ...

  9. 【重走Android之路】【Java面向对象基础(二)】细说String、StringBuffer和StringBuilder

    [重走Android之路][基础篇(二)][Java面向对象基础]细说String.StringBuffer和StringBuilder   1.String String是Java中的一个final ...

随机推荐

  1. C# DataSet数据导入Excel 修正版- .net FrameWork 4.0以上

    引入  Microsoft.Office.Interop.Excel.dll 格式:标题加了下划线,单元格内容居中 1 using System; using System.Data; using S ...

  2. 【mp3】洗脑循环了!龙珠超 自在极意功 【究极の圣戦】串田アキラ 背景纯音乐

    自在极意功情况下发动自带bgm 曲名:究极の圣戦 首先是视频: http://dwz.cn/6Tj2Lq 然后是mp3:度盘下载>> 老外翻唱: 个人翻唱:全民k歌>>

  3. Coursera课程 Programming Languages, Part B 总结

    Programming Languages, Part A Programming Languages, Part B Part A 笔记 碎言碎语 很多没有写过 Lisp 程序的人都会对 Lisp ...

  4. NPOI操作Excel 踩坑记

    1 读取Excel并修改单元格 a.一定不能一边读数据,一边修改单元格,否则读出来的数据可能不准 b.注意写文件的模式,不然修改后的文件,打开会报错. c.清空单元格的数据,可以调用SetCellTy ...

  5. python 使用paramiko模块上传本地文件到ssh

    我们要了解几个函数: paramiko.Tranport(("目标ip,端口"))#这是上传目标的IP和端口 paramiko.SFTPClient.from_tranport() ...

  6. hdu_4497GCD and LCM(合数分解)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4497 GCD and LCM Time Limit: 2000/1000 MS (Java/Other ...

  7. 一步一步从原理跟我学邮件收取及发送 3.telnet命令行发一封信

    首先要感谢博客园管理员的及时回复,本系列的第二篇文章得以恢复到首页,这是对作者的莫大鼓励.说实在的本来我真的挺受打击的.好在管理员说只是排版上有些问题,要用代码块修饰下相关的信息.说来惭愧因为常年编码 ...

  8. HTML 和 PHP 、MySQL 的交互

    为什么要用到数据库? World Wide Web (WWW)不仅仅是一个提供信息的地方.如果你有什么东西,作一个网站,同样可以和全世界的人一起分享.但是,这并不是一件很容易的事.当网站越做越大时,你 ...

  9. FineReport父子格实现动态参数注入

    "深入学习FineReport后发现其功能及其强大,之前使用存储过程实现的报表完全可以使用FineReport本身的功能实现. 当你需要的表名,查询条件等均未知的时候,使用"动态参 ...

  10. volatile 与 synchronized 区别

    在Java中,为了保证多线程读写数据时保证数据的一致性,可以采用两种方式: 同步 如用synchronized关键字,或者使用锁对象. volatile 使用volatile关键字用一句话概括vola ...