是OOP和完全避免实现继承可能吗?(Is OOP & completely avoiding imp

2019-06-28 05:53发布

我会选择Java作为一个例子,大多数人都知道它,但所有其他OO语言是工作也是如此。

Java中,像许多其他语言,具有接口继承和实现继承。 例如,一个Java类可以从另一个之一,每件有落实有(假设父是不是抽象的),是继承的方法继承了。 这意味着,在继承了接口和该方法的实施,以及。 我可以覆盖它,但我没有。 如果我不覆盖它,我继承的实现。

然而,我的类还可以“继承”(不是在Java术语)只是一个接口,没有实现。 实际上接口真名叫Java中这种方式,他们提供的接口继承,但没有继承任何实现,因为一个接口的所有方法都没有实现。

现在有这样一篇文章,说这是更好的继承不是实现接口 ,您可能想了解它(至少在第一页的前半部分),这是很有趣的。 它避免类似问题的脆弱的基类问题 。 到目前为止,这使所有有很大的意义和许多其他的事情在文章中说做了很多有意义的我。

什么错误我这个,就是实现继承是指代码的重用 ,面向对象语言的最重要的属性之一。 现在,如果Java的没有课,它解决了实现继承的所有问题(如詹姆斯·高斯林,Java的教父根据这篇文章希望),但你会如何做的代码重用可能呢?

例如:如果我有一个类汽车及汽车有一个方法移动(),这使得汽车的举动。 现在,我可以针对不同类型的汽车,这都是汽车,但汽车的所有专门版本的子级车。 有些人可能会以不同的方式移动,这些都需要改写移动()反正,但大多数人仅保留继承的举动,因为他们都移动,就像抽象父车。 现在承担第二,有在Java中唯一的接口,只有接口可以相互继承,一个类可以实现接口,而且所有的课总是最后的,所以没有类可以从其它类继承。

你将如何避免当你有一个接口汽车和hundred汽车类,你需要实现相同的举动为他们每个人的()方法? 在面向对象的世界中存在的代码重用什么概念,除了实现继承?

有些语言有混入。 是否混入了回答我的问题? 我了解他们,但我真的不能想象如何混入将在Java世界中工作,如果他们能真正解决这里的问题。

另一个想法是,有是仅实现汽车接口的类,我们称之为AbstractCar,并实现了move()方法。 现在其他汽车实现汽车界面,以及在内部他们创造AbstractCar的一个实例,它们通过调用其内部抽象汽车移动()实现自己的move()方法。 但是,这是不是可以浪费资源白白(一个方法调用只是另一种方法 - 好吧,JIT可以内联的代码,但仍),并使用额外的内存保持内部对象,你甚至不会需要实现继承? (所有每对象需要比封装数据的简单相加更多的内存后)也不是很难堪的程序员写虚方法,如

public void move() {
    abstractCarObject.move();
}

任何人都可以想像一个更好的主意如何避免实现继承,仍然能够以简单的方式重新使用的代码?

Answer 1:

简短的回答:是的,它是可能的。 但是,你必须这样做目的和没有偶然(用决赛中,抽象和设计时考虑到继承等)

长一点的回答:

嗯,继承实际上不是“代码复用”,它是一流的“专业化”,我认为这是一种误解。

比如它是一个非常糟糕的主意,以创建从Vector堆栈,只是因为他们是一样的。 或哈希表的属性,只是因为他们存储的值。 参见[有效。

在“代码重用”是的OO特性更多的是“业务视图”,意思是你对象是节点之间容易分派; 并且是便携,并没有没有以前的编程语言产生的问题。 这已被证明是半分辩。 现在,我们有了可方便地分发库; 例如在Java中的jar文件可以在任何项目中节省数千发展的时段使用。 OO仍然有一些问题与便携性之类的东西,就是这个原因,现在Web服务是如此受欢迎(因为之前它是CORBA),但这是另一个线程。

这是“代码重用”的一个方面。 另一种是有效的,具有与编程做一个。 但是,在这种情况下,不仅是“拯救”的代码行和创建脆弱的怪物,但要注意设计继承。 这是前面提到的那本书的第17项; 项目17:设计和文档继承,否则禁止。 参见[有效]

当然,你可以有子类的汽车级和万吨。 是的,你提到关于汽车的接口,AbstractCar和CarImplementation的办法是走的正确道路。

您定义的“合同”的汽车要坚持说这些都是在谈论汽车时,我希望有方法。 抽象的汽车拥有每车,但离开和记录的子类负责处理方法的基本功能。 在Java中,你通过标记方法,抽象做到这一点。

当你采用这种方式,没有与“脆弱”类问题(或者至少设计师是有意识或威胁)和子类做完整的只有这些部件的设计允许它们。

继承是更“专业”的课程,以同样的方式一卡车Car的特殊版本,和卡车的MosterTruck一个特殊版本。

它不会使三色打造从汽车中的“ComputerMouse” subclase只是因为它有一个轮子(滚轮)就像一辆汽车,它的动作,并具有以下只是为了节省的代码行的轮子。 它属于不同的域,它会被用于其他目的。

防止“执行”继承的方式是从一开始,你应该使用final关键字类声明,并通过这种方式你是禁止的子类的编程语言。

如果它是有目的的子类化不是罪恶。 如果它这样做uncarefully它可能成为一场噩梦。 我要说的是,你应该开始为私人和“最终”成为可能,如果需要,使事情变得更加公开和扩展,能。 这也被广泛地在演示文稿中解释说,“如何设计良好的API和它为什么重要”参见[好API]

继续阅读文章,随着时间的推移和实践(和很大的耐心)这件事会更清晰。 虽然有时你只需要做的工作和复制/粘贴一些代码:P。 这是确定的,只要你尽力把它做好第一次。

这里有两个从约书亚布洛赫(原Sun合作,在Java的核心,现就职于谷歌)的引用


[功效]有效的Java。 绝对是最好的Java书非初学者应该学习,理解和实践。 A必须有。

有效的Java


[好API]介绍,关于API的设计,可重用性和相关主题的会谈。 这是一个有点冗长,但它每分钟的价值。

如何设计一个良好的API和重要性

问候。


更新:看看我送你的视频链接的分42。 它谈论这个话题:

“当你有一个公共的API在两个阶级,你认为自己做一把,另一子类,像富是酒吧的一个子类,问你自己,是每一个富吧?......”

而在以前分钟就谈论“代码重用”,而谈到TimeTask。



Answer 2:

与对继承最例子的问题就是例子,而该人被错误地使用继承,而不是继承正确抽象的失败。

在您发布链接到文章中,作者展示了使用堆栈和ArrayList继承的“破碎”。 的例子中是有缺陷的,因为堆栈不是一个ArrayList,因此不应该使用继承。 的例子是作为有缺陷的字符串延伸字符,或PointXY延伸数目。

在您扩展类,你应该始终执行“is_a”的考验。 既然你不能说每一个堆栈是没有被误以某种方式一个ArrayList,那么你不应该inheirit。

堆栈的合同比合同的ArrayList(或目录)和堆栈不同不应该继承的方法就是不关心(如获取(int i)以添加())。 事实上堆栈应该与方法,如接口:

interface Stack<T> {
   public void push(T object);
   public T pop();
   public void clear();
   public int size();
}

像ArrayListStack一类有可能实现堆栈接口,并且在这种情况下使用的组合物(具有内部的ArrayList),而不是继承。

继承是不坏,坏的继承是坏的。



Answer 3:

你也可以使用成分和战略格局。 链接文本

public class Car
{
  private ICar _car;

  public void Move() {
     _car.Move();
  }
}

这比使用基于继承行为,因为它可以让你在运行时改变,通过根据需要替换新车的类型更加灵活。



Answer 4:

您可以使用组成 。 在你的榜样,一个Car对象可能包含称为传动系统另一个对象。 该车的move()方法可以简单地把它的动力系统的驱动器()方法。 动力传动系统类可以反过来,包含像发动机,变速箱,车轮,等等。如果你的结构类层次结构这种方式,你可以很容易地创建汽车,其以不同的方式将它们组成的简单零件的不同组合的移动物体(即重用代码)。



Answer 5:

为了使混入/成分更容易,看看我的注释和批注处理器:

http://code.google.com/p/javadude/wiki/Annotations

特别地,混入例如:

http://code.google.com/p/javadude/wiki/AnnotationsMixinExample

需要注意的是目前它没有工作,如果被委派接口/类型有参数的方法(或参数化类型的方法)。 我正在上...



Answer 6:

这很有趣,回答我的问题,但这里的东西,我发现这是非常有趣的: Sather 。

这是一种编程语言,没有实现继承可言! 它知道界面(叫做抽象类没有实现或封装的数据),并且接口可以相互继承遗产(实际上,他们甚至支持多重继承!),但一个类只能实现接口(抽象类,多达它喜欢)它不能从其他类继承。 但它可以“包含”另一个类。 这是相当委托的概念。 包括类必须在类的构造函数实例化,当你的类被销毁被销毁。 除非你覆盖他们有方法,你的类继承其接口为好,但不是他们的代码。 取而代之的方法是创建只是将呼叫转移到你的方法所包括的对象同样命名的方法。 包括对象,只是封装的对象之间的区别是,你不必创建委派转发自己和他们不存在,你可以绕过作为独立的对象,他们是你的对象的一部分,生活,更同归于尽您对象(或更多技术上的话,说:你的对象和所有包含的人的记忆与单个ALLOC电话,同一个内存块中创建的,你只需要初始化他们在你的构造函数调用,使用真正的代表时,同时,每个这些对象的原因一个自己的页头调用,拥有自己的内存块,并完全能够独立生活的对象)。

语言是不是很漂亮,但我喜欢它的设计思想:-)



Answer 7:

继承是没有必要的面向对象语言。

考虑的Javascript,这更加面向对象比Java,按理说。 有没有课,只是对象。 码是通过将现有的方法的一个对象重新使用。 JavaScript对象本质上是一个地图名称功能(和数据),其中,所述地图的初始内容是通过一个原型建立,并且新的条目可被添加到在飞行中的给定实例的。



Answer 8:

你应该阅读设计模式。 你会发现,接口是许多类型的有用的设计模式的关键。 例如抽象的不同类型的网络协议将具有相同的接口(该软件调用它),但因为每种类型的协议的不同行为少的代码重用。

对于一些算法开眼在展示如何把一个节目的众多元素一起做一些有用的任务。 设计模式做objects.Shows如何在执行有用的任务的方式对象合并相同。

设计模式的四人帮



文章来源: Is OOP & completely avoiding implementation inheritance possible?
标签: java oop