菜鸟译文(一)——Java中的继承和组合
阅读英文的能力对于程序员来说,是很重要的。这几年也一直在学习英文,今天心血来潮,就在网上找了一篇简短的博文翻译一下。水平一般,能力有限,还请各位看官多多指点。
译文:
本文将会举例说明Java中继承和组合的概念。首先举一个继承的例子,然后展示一下如何用组合来改善继承的设计。最后概括一下如何在它们之间做出选择。
1. 继承
假设我们有一个Insect类。这个类包含两个方法:一个是move(),一个是attack()。
class Insect {
private int size;
private String color; public Insect(int size, String color) {
this.size = size;
this.color = color;
} public int getSize() {
return size;
} public void setSize(int size) {
this.size = size;
} public String getColor() {
return color;
} public void setColor(String color) {
this.color = color;
} public void move() {
System.out.println("Move");
} public void attack() {
move(); //assuming an insect needs to move before attacking
System.out.println("Attack");
}
}
现在你想定义一个Bee类,它是Insect类型的,但是有着不同实现的attack()方法和move()方法。我们可以用继承来设计,如下所示:
class Bee extends Insect {
public Bee(int size, String color) {
super(size, color);
} public void move() {
System.out.println("Fly");
} public void attack() {
move();
super.attack();
}
} public class InheritanceVSComposition {
public static void main(String[] args) {
Insect i = new Bee(1, "red");
i.attack();
}
}
类层次结构关系图就是如此简单:
输出:
Fly
Fly
Attack
"Fly"被打印了两次,表示move()被调用了两次。但是它应该被调用了一次才对。
问题出在super.attack()方法上。Insect的attack()方法调用move()方法。当子类调用super.attack()时,总是会调用重写的move()方法。
我们可以用下面的方法解决这个问题:
- 去掉子类的attack()方法。这将使子类取决于父类attack()方法的实现,如果父类中的attack()方法发生改变(这是你无法控制的),例如:父类的attack()方法使用其他的方式来实现,子类也需要跟着改变,这不是好的设计。
- 重写attack()方法,如下:
public void attack() {
move();
System.out.println("Attack");
}这样能保证正确的结果,因为子类不再依赖于父类 。然而, 代码变成了一个父类的复制品。(想象一下,attack()方法远比打印一个字符串要复杂的多)这违背了软件工程复用的原则。
这个继承的设计不好,因为子类依赖父类的具体实现,如果父类发生变化,子类将被破坏。
2. 组合
与继承相反,组合可以用于这种情况。让我们先看看使用组合的解决方法。
attack方法被抽象为一个接口。
interface Attack {
public void move();
public void attack();
}
可以对Attack接口进行多种不同的实现。
class AttackImpl implements Attack {
private String move;
private String attack; public AttackImpl(String move, String attack) {
this.move = move;
this.attack = attack;
} @Override
public void move() {
System.out.println(move);
} @Override
public void attack() {
move();
System.out.println(attack);
}
}
将attack方法抽出来,Insect就不再与attack相关联了。
class Insect {
private int size;
private String color; public Insect(int size, String color) {
this.size = size;
this.color = color;
} public int getSize() {
return size;
} public void setSize(int size) {
this.size = size;
} public String getColor() {
return color;
} public void setColor(String color) {
this.color = color;
}
}
Bee是一个Insect的类型,它可以攻击。
// This wrapper class wrap an Attack object
class Bee extends Insect implements Attack {
private Attack attack; public Bee(int size, String color, Attack attack) {
super(size, color);
this.attack = attack;
} public void move() {
attack.move();
} public void attack() {
attack.attack();
}
}
类图:
public class InheritanceVSComposition2 {
public static void main(String[] args) {
Bee a = new Bee(1, "black", new AttackImpl("fly", "move"));
a.attack(); // if you need another implementation of move()
// there is no need to change Insect, we can quickly use new method to attack Bee b = new Bee(1, "black", new AttackImpl("fly", "sting"));
b.attack();
}
}
fly
move
fly
sting
3. 何时用继承,何时用组合?
下面两条内容,可以告诉我们如何在继承与组合之间做出选择:
- 如果存在一个“是”的关系,并且一个类要对另一个类公开所有的接口,那么继承是更好的选择
- 如果存在一个“有”的关系,那么首选组合。
总之,继承和组合都有其用途,和理解他们的优缺点是很有必要的。
最后说一点自己的感受吧,小弟自打初中开始学英语,成绩就没好过,最好成绩也就刚及格吧。记得当年高考的时候lz的英语成绩是55分(足以载入史册的成绩),我的英文水平有多差,大家可想而知了吧。后来承蒙恩师的谆谆教诲,一直没有放弃英语的学习,现在依然每天都在学(虽然没有掌握其精髓,但是学总比不学强)。以前遇到外国人根本张不开嘴,不知道说什么,现在好多了,之前经常跟老外一起踢球,没事瞎白话几句,感觉也挺好玩的。以前看到英文的文章,直接关掉,现在也能静下心来看下去了。
总之,学英语心态很重要,只要你不怕它,它就没什么好怕的。毛主席曾说过:“All the reactionaries are the Papertiger(一切反动派都是纸老虎)”。英语没什么好怕的,遇到老外你就跟他瞎扯呗,最不济你俩打个平手——谁也听不懂谁说什么。还有更坏的结果吗?不管怎样咱都不会输,那你还怕啥?看英文文章、书籍看不懂,那就更不用怕了,大不了弄个词典呗,我大有道在手,还怕治不了你个小英文了。别犹豫了,上吧,少年!
原文链接: Inheritance vs. Composition in Java
菜鸟译文(一)——Java中的继承和组合的更多相关文章
- 关于Java中的继承和组合的一个错误使用的例子
[TOC] 关于Java中的继承和组合的一个错误使用的例子 相信绝大多数人都比较熟悉Java中的「继承」和「组合」这两个东西,本篇文章就主要就这两个话题谈论一下.如果我某些地方写的不对,或者比较幼稚, ...
- <Java中的继承和组合之间的联系和区别>
//Java中的继承和组合之间的联系和区别 //本例是继承 class Animal { private void beat() { System.out.println("心胀跳动...& ...
- Java中的继承与组合(转载)
本文主要说明Java中继承与组合的概念,以及它们之间的联系与区别.首先文章会给出一小段代码示例,用于展示到底什么是继承.然后演示如何通过“组合”来改进这种继承的设计机制.最后总结这两者的应用场景,即到 ...
- Java中的继承与组合
本文主要说明Java中继承与组合的概念,以及它们之间的联系与区别.首先文章会给出一小段代码示例,用于展示到底什么是继承.然后演示如何通过“组合”来改进这种继承的设计机制.最后总结这两者的应用场景,即到 ...
- [译]Java中的继承 VS 组合
(文章翻译自Inheritance vs. Composition in Java) 这篇文章阐述了Java中继承和组合的概念.它首先给出了一个继承的例子然后指出怎么通过组合来提高继承的设计.最后总结 ...
- java中的继承与oc中的继承的区别
为什么要使用继承? 继承的好处: (1)抽取出了重复的代码,使代码更加灵活 (2)建立了类和类之间的联系 继承的缺点: 耦合性太强 OC中的继承 1.OC中不允许子类和父类拥有相同名称的成员变量名:( ...
- Java中的继承
我们在以前的学习中,我们会了C#中的继承,今天我们来了解了解Java中的继承,其实都大同小异啦! 1.语法 修饰符 SubClass extends SuperClass(){ //类定义部分 } e ...
- extends:类似于java中的继承特征,extends="struts-default"
extends:类似于java中的继承特征,extends="struts-default"就是继承struts-default.xml,它里面定义了许多跳转类型.拦截器等一些常用 ...
- 关于java中的继承
我们都知道Java中的继承是复用代码.扩展子类的一种方式,继承使得Java中重复的代码能够被提取出来供子类共用,对于Java程序的性能以及修改和扩展有很大的意义,所以这是一个非常重要的知识点. 那么对 ...
随机推荐
- JUC-ReadWriteLock
ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作.只要没有 writer,读取锁可以由多个 reader 线程同时保持.写入锁是独占的. ReadWriteLock ...
- windows 10 更新失败及应用商店重装问题解决记录
简单的记录一下这次遇到的问题及解决办法. 使用的windows 10 企业版一直不能更新成功,各种办法都试过了,都是失败然后回退. 这次直接下载了1709的映像进行升级安装的,因为我的是双系统,升级安 ...
- Mysql中字符串正确的连接方法
虽然SQL server和My sql的语句基本都一致,但是仍然存在一些小区别.就如字符串的连接来说,SQL server中的字符串连接是使用“+”来连接,不带引号sql server是做加法运算.而 ...
- MongoDB安装实录
mongodb是nosql中的贵族,很受欢迎... 01.下载 官方:https://www.mongodb.com 社区版.企业版 https://www.mongodb.com/downloa ...
- 转:关于 OGRE 与 OSG 的简单比较
1 前言 我曾经细致阅读过 OGRE 和 OSG 官方提供的文档,有<Pro OGRE 3D Programming>.OGRE自带手册(manual).王锐老师等翻译的<Ope ...
- 在发送信息时应用PendingIntent.FLAG_UPDATE_CURRENT
1. 连续发送两条信息时,出现bug.以下是bug现象描述. 发送第一条信息,sentReceiver弹出toast告知发送成功,同时在listview中的发送状态立即同步更新为发送成功. 继续发送第 ...
- Mac系统清理、占用空间大、空间不够、查看系统文件大小分布
背景: 最近老提示空间不够,很尴尬,一直弹系统提示 如图,256的空间,就剩下几个G了,其中最大头的系统占用:160G,占比60%多 正常情况下:我们可以点击管理,进入到系统磁盘优化界面: 这种适用于 ...
- <转>LUA语法分析
本文选自:http://www.cnblogs.com/nazhizq/p/6516561.html 一步步调试,在lparser.c文件中luaY_parser函数是语法分析的重点函数,词法分析也是 ...
- hihocoder第226周:打表找规律
题目列表 问题描述 有一个文本框,可以执行以下操作: 输入A Ctrl+C 复制 Ctrl+V 粘贴 Ctrl+A 全选 N次操作最多能够造出多少个A来? 输入一个N,输出一个整数,表示最多有多少个A ...
- java面试题--实现一个百亿的计算器
看了网上很多说法,没有具体把它实现的,我试了一下其实还是比较简单的. 直接看代码: package com.infomorrow; import java.math.BigInteger; impor ...