构成与继承

组成与继承是面试中经常被问到的问题之一。你一定也听说过使用组合而不是继承。

组合vs继承

组合和继承都是面向对象编程concepts.它们不与Java等任何特定编程语言捆绑在一起。在我们以编程方式比较组合和继承之前,让我们先快速定义一下它们。

组成

组合是面向对象编程中的一种设计技术,用于实现对象之间的 has-a 关系。Java中的组合是通过使用其他对象的实例变量来实现的。例如,一个有工作的人在java面向对象编程中实现如下。

1package com.journaldev.composition;
2
3public class Job {
4// variables, methods etc.
5}
1package com.journaldev.composition;
2
3public class Person {
4
5    //composition has-a relationship
6    private Job job;
7
8    //variables, methods, constructors etc. object-oriented

继承

继承是面向对象编程中实现对象间 关系的设计技术。Java中的继承是使用扩展关键字实现的。例如,猫是一种动物关系,在Java编程中将实现如下。

1package com.journaldev.inheritance;
2
3public class Animal {
4// variables, methods etc.
5}
1package com.journaldev.inheritance;
2
3public class Cat extends Animal{
4}

组合继承

组合和继承都通过不同的方法促进代码重用。那么,该选哪一个呢?如何比较组合和继承。您一定听说过,在编程中,您应该优先考虑组合而不是继承。让我们来看看一些原因,它们将帮助您选择组合还是继承。

1.继承是紧耦合的,而组合是松耦合的。让我们假设我们有下面的继承类。

 1Com.Jouraldev.java.Examples包;
 2
 3公共类A类{
 4
 5公共无效foo(){
 6}
 7}
 8
 9类B扩展了类A{
10公共无效酒吧(){
11
12}
13}
14为简单起见,我们在一个包中同时包含了超类和子类。但大多数情况下,它们将位于单独的代码库中。可以有许多类扩展超类ClassA。这种情况的一个非常常见的例子是扩展异常类。现在假设ClassA实现如下所示,添加了一个新方法bar()。`
15Com.Jouraldev.java.Examples包;
16
17公共类A类{
18
19公共无效foo(){
20}
21
22公共int bar(){
23返回0;
24}
25}
26`一旦开始使用新的ClassA实现,就会在ClassB中得到编译时错误,因为`返回类型与ClassA.bar()不兼容`。解决方案是更改超类或子类bar()方法以使它们兼容。如果您使用组合而不是继承,您将永远不会面临这个问题。下面是使用组合实现ClassB的一个简单示例。`
27B类{
28类别A类别A=新类别A();
29
30公共无效酒吧(){
31ClassA.foo();
32ClassA.bar();
33}
34}

2.继承中没有访问控制,组合中可以限制访问。我们将所有超类方法公开给其他有权访问子类的类。因此,如果引入新方法或超类中存在安全漏洞,子类就会变得易受攻击。因为在组合中我们选择要使用的方法,所以它比继承更安全。例如,我们可以使用ClassB中的以下代码向其他类提供ClassA foo()方法公开。

 1B类{
 2
 3类别A类别A=新类别A();
 4
 5公共无效foo(){
 6ClassA.foo();
 7}
 8
 9公共无效酒吧(){
10}
11
12}
13这是合成相对于继承的主要优势之一。
143.组合提供了调用方法的灵活性,这对于多子类场景很有用。例如,假设我们有下面的继承场景。

抽象类Abs{ 抽象空foo(); }

公共类ClassA扩展了Abs{

公共无效foo(){ }

}

类ClassB扩展了Abs{

公共无效foo(){ }

}

类测试{

类别A a=新类别A(); B类b=新B类(ClassB);

公共无效测试(){ A.foo(); B.foo(); } } 那么,如果有更多的子类,组合会不会因为每个子类有一个实例而使我们的代码难看呢?不,我们可以如下所示重写测试类。` 类测试{ ABS obj=空;

测试1(Abs O){ This.obj=o; }

公共无效foo(){ This.obj.foo(); }

} 这将使您可以根据构造函数中使用的对象灵活地使用任何子类。 4.组合相对于继承的另一个好处是测试范围。单元测试在组合上很容易,因为我们知道我们从另一个类使用的所有方法。我们可以模拟它进行测试,而在继承中,我们严重依赖超类,不知道超类的所有方法都将被使用。因此,我们将不得不测试超类的所有方法。这是额外的工作,因为继承,我们需要做不必要的工作。

这就是关于组合和继承的全部。你有足够的理由选择组合而不是继承。只有当您确定超类不会被更改时才使用继承,否则使用组合。

Published At
Categories with 技术
Tagged with
comments powered by Disqus