J a v a 的“多重继承”
接口只是比抽象类“更纯”的一种形式。它的用途并不止那些。由于接口根本没有具体的实施细节——也就
是说,没有与存储空间与“接口”关联在一起——所以没有任何办法可以防止多个接口合并到一起。这一点
是至关重要的,因为我们经常都需要表达这样一个意思:“x 从属于a,也从属于b,也从属于c”。在C++
中,将多个类合并到一起的行动称作“多重继承”,而且操作较为不便,因为每个类都可能有一套自己的实
施细节。在Java 中,我们可采取同样的行动,但只有其中一个类拥有具体的实施细节。所以在合并多个接口
的时候,C++的问题不会在Java 中重演。如下所示:

在一个衍生类中,我们并不一定要拥有一个抽象或具体(没有抽象方法)的基础类。如果确实想从一个非接
口继承,那么只能从一个继承。剩余的所有基本元素都必须是“接口”。我们将所有接口名置于implements
关键字的后面,并用逗号分隔它们。可根据需要使用多个接口,而且每个接口都会成为一个独立的类型,可
对其进行上溯造型。下面这个例子展示了一个“具体”类同几个接口合并的情况,它最终生成了一个新类:
//: Adventure.java
// Multiple interfaces
import java.util.*;
interface CanFight {
void fight();
}
interface CanSwim {
void swim();
}
interface CanFly {
void fly();
}
class ActionCharacter {
public void fight() {}
}
class Hero extends ActionCharacter
implements CanFight, CanSwim, CanFly {
public void swim() {}
public void fly() {}
}
public class Adventure {
static void t(CanFight x) { x.fight(); }
static void u(CanSwim x) { x.swim(); }
static void v(CanFly x) { x.fly(); }
static void w(ActionCharacter x) { x.fight(); }
public static void main(String[] args) {
Hero i = new Hero();
t(i); // Treat it as a CanFight
u(i); // Treat it as a CanSwim
v(i); // Treat it as a CanFly
w(i); // Treat it as an ActionCharacter
}
} ///:~
从中可以看到,Hero 将具体类ActionCharacter 同接口CanFight,CanSwim 以及CanFly 合并起来。按这种
形式合并一个具体类与接口的时候,具体类必须首先出现,然后才是接口(否则编译器会报错)。
请注意fight()的签名在CanFight 接口与ActionCharacter 类中是相同的,而且没有在Hero 中为fight()提
供一个具体的定义。接口的规则是:我们可以从它继承(稍后就会看到),但这样得到的将是另一个接口。
如果想创建新类型的一个对象,它就必须是已提供所有定义的一个类。尽管Hero 没有为fight()明确地提供
一个定义,但定义是随同ActionCharacter 来的,所以这个定义会自动提供,我们可以创建Hero 的对象。
在类Adventure 中,我们可看到共有四个方法,它们将不同的接口和具体类作为自己的自变量使用。创建一
个Hero 对象后,它可以传递给这些方法中的任何一个。这意味着它们会依次上溯造型到每一个接口。由于接
口是用Java 设计的,所以这样做不会有任何问题,而且程序员不必对此加以任何特别的关注。
注意上述例子已向我们揭示了接口最关键的作用,也是使用接口最重要的一个原因:能上溯造型至多个基础
类。使用接口的第二个原因与使用抽象基础类的原因是一样的:防止客户程序员制作这个类的一个对象,以
176
及规定它仅仅是一个接口。这样便带来了一个问题:到底应该使用一个接口还是一个抽象类呢?若使用接
口,我们可以同时获得抽象类以及接口的好处。所以假如想创建的基础类没有任何方法定义或者成员变量,
那么无论如何都愿意使用接口,而不要选择抽象类。事实上,如果事先知道某种东西会成为基础类,那么第
一个选择就是把它变成一个接口。只有在必须使用方法定义或者成员变量的时候,才应考虑采用抽象类。
J a v a 的“多重继承”的更多相关文章
- JavaScript针对Dom相关的优化心得
JavaScript针对Dom相关的优化心得 组内同时总结的关于javascript性能优化注意些节.记录一下. 1. 批量增加 Dom 尽量使用修改 innerHTML 的方式而不是用 append ...
- JAVA中String对象的比较
JAVA中String对象的比较 1.首先介绍三个String对象比较的方法:(1)equals:比较两个String对象的值是否相等.例如: String str1 = "hello qu ...
- XV Open Cup named after E.V. Pankratiev. GP of Tatarstan
A. Survival Route 留坑. B. Dispersed parentheses $f[i][j][k]$表示长度为$i$,未匹配的左括号数为$j$,最多的未匹配左括号数为$k$的方案数. ...
- XVII Open Cup named after E.V. Pankratiev. GP of SPb
A. Array Factory 将下标按前缀和排序,然后双指针,维护最大的右边界即可. #include<cstdio> #include<algorithm> using ...
- XVI Open Cup named after E.V. Pankratiev. GP of Ukraine
A. Associated Vertices 首先求出SCC然后缩点,第一次求出每个点能到的点集,第二次收集这些点集即可,用bitset加速,时间复杂度$O(\frac{nm}{64})$. #inc ...
- XVI Open Cup named after E.V. Pankratiev. GP of Siberia
A. Passage 枚举两个点,看看删掉之后剩下的图是否是二分图. #include <bits/stdc++.h> using namespace std ; const int MA ...
- XVI Open Cup named after E.V. Pankratiev. GP of Ekaterinburg
A. Avengers, The 留坑. B. Black Widow 将所有数的所有约数插入set,然后求mex. #include<bits/stdc++.h> using names ...
- XVI Open Cup named after E.V. Pankratiev. GP of SPB
A. Bubbles 枚举两个点,求出垂直平分线与$x$轴的交点,答案=交点数+1. 时间复杂度$O(n^2\log n)$. #include<cstdio> #include<a ...
- XIV Open Cup named after E.V. Pankratiev. GP of SPb
A. Bracket Expression 直接按题意模拟即可. 时间复杂度$O(n)$. #include<stdio.h> #include<algorithm> #inc ...
随机推荐
- Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收
执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链.函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境.全局执行环境 ...
- 前端开发中SEO的十二条总结
一. 合理使用title, description, keywords二. 合理使用h1 - h6, h1标签的权重很高, 注意使用频率三. 列表代码使用ul, 重要文字使用strong标签四. 图片 ...
- shell简介
Shell作为命令语言,它交互式地解释和执行用户输入的命令:作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支. shell使用的熟练程度反映了用户对U ...
- Android混合开发之WebView与Javascript交互
前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...
- [C#] 简单的 Helper 封装 -- SQLiteHelper
using System; using System.Data; using System.Data.SQLite; namespace SqliteConsoleApp { /// <summ ...
- 几个有趣的WEB设备API 前端提高B格必备(一)——电池状态&震动api
受到同事启发,突然发现了几个有趣又实用的web api,没想到前端还有这么多有趣的东西可以玩~~简直过分. 1.电池状态API navigator.getBattery():这个api返回的是一个pr ...
- 【Python五篇慢慢弹】快速上手学python
快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...
- 【从零开始学BPM,Day2】默认表单开发
[课程主题]主题:5天,一起从零开始学习BPM[课程形式]1.为期5天的短任务学习2.每天观看一个视频,视频学习时间自由安排. [第二天课程] Step 1 软件下载:H3 BPM10.0全开放免费下 ...
- 简历生成平台项目开发-STEP1问卷设计
周五课程结束完后,小组建立QQ群和微信群,着手讨论项目问题.一开始的大概想法:就业信息平台,收集企业招聘信息和就业生资料,提供给学生和企业的校企对接平台.后来发现群里谭卓同学也有个相关的思路,经过商量 ...
- 使用PushSharp给iOS应用推送消息
PushSharp是一个C#编写的服务端类库,用于推送消息到各种客户端,支持iOS(iPhone/iPad).Android.Windows Phone.Windows 8.Amazo.Blackbe ...