首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Java中对可选继承建模

如何在Java中对可选继承建模
EN

Stack Overflow用户
提问于 2020-09-05 03:48:34
回答 3查看 371关注 0票数 3

是否有一种方式可选继承,如下面的案例所述?

说从这个开始:

注意:可以有4个以上的子类。

现在有一个可选的功能,叫做“自主传输”,就像这里。

选项1:如上图所示,我可以让所有的子类继承自“自主传输”,但我不想这样做。比如说,不可能有一辆自动驾驶的火车。

选项2:没有严格的“自主运输”,而是让单独的类根据需要继承(可能带有接口),比如“汽车”,“自动汽车”,“卡车”,“自动卡车”。但不是一个有吸引力的选择,因为有4个以上的子类

选项3:可能的,我可以使用依赖注入并在需要的地方注入“自治”功能,但我不能添加任何像dagger之类的框架。

有没有其他方法,可以用Java干净利落地完成?基本上,如果“列车”不能自主,我不想在那里有任何相关的业务逻辑。

EN

回答 3

Stack Overflow用户

发布于 2020-09-06 14:33:05

要保持简单,请执行以下操作:

选项1

代码语言:javascript
运行
复制
abstract class Transport {
   foo();
} 

abstract class AutomonousTransport extends Transport {
   bar();
}

class Car extends AutonomousTransport {
   // inherits foo and bar
}

class Train extends Transport {
   //inherits only foo(), which is ok, since Train is still a transport 
}

使用这种方法,您必须决定从哪个类继承,以便获得所需的功能。

这种方法的潜在缺点是,如果你有许多不同的功能,就像这样(在java中,你只能从一个类扩展)。

要解决此问题,如果您只继承功能(行为)而不是状态,请考虑将接口与默认方法一起使用,而不是使用抽象类。这在某种程度上类似于其他语言中的特征,但有一些限制:

代码语言:javascript
运行
复制
interface Transport {
   default foo () {...} 
}

interface AutonomousTransport extends Transport {
   default bar() {}
}
interface WheelSupportTransport extends Transport {
   default rotateWheelLeft() {...}
   default rotateWheelRight() {...}
}

class Car implements AutomonousTransport, WheelSupportTransport  {
   
}

class Train implements Transport {...}

选项2

代码语言:javascript
运行
复制
abstract class Transport {
   foo() 
}

final class AutonomousStuff { // final to prohibit inheritance from it
   bar()
}

class Car extends Transport {
   AutonomousStuff autonomousStuff;
}

class Train extends Transport {
   // only foo
}

这种方法基于“优先组合而不是继承”的思想。您可以将行为作为内部数据字段添加到必需的类中,并通过此字段获得对所需方法(功能)集的访问权限。

选项3

代码语言:javascript
运行
复制
abstract class Transport {
   foo()
}

abstract class AutonomousCapable extends Transport {
    private final Transport transport;
    public AutonomouseCapable(Transport transport) {
       this.transport  =  transport;
    }
    bar()

    foo() {
        transport.foo();
    }
    
}

class Car extends Transport {}

class Train extends Transport {} 

创建汽车时,请使用new AutonomousCapable(new Car())

这遵循了“装饰者”的概念。包装器)模式。您可以在运行时使用一组额外的行为来“装饰”对象(汽车)。

票数 3
EN

Stack Overflow用户

发布于 2020-09-05 04:11:46

如果自治是一个可选的功能,那么它实际上并不是所有子类的泛化属性。

在我看来,它应该是4个抽象类AbstractCarAbstractTruck等,然后你可以对每个抽象类有两个具体的实现,比如AutonomousCarNonAutonomousCar。一个是自主的,另一个不是。

您可以为自治类提供一个名为IAutonomousTransport的标记接口

当然,上面的假设是您不希望在类中有一个名为isAutonomous的简单标志,并基于此处理您的功能。但是这个方法不会是多态的。

票数 1
EN

Stack Overflow用户

发布于 2020-09-06 14:49:51

你应该在这里使用Decorator Pattern

代码语言:javascript
运行
复制
public interface Transport {
    void foo();
}

public class AutonomousTransport implements Transport {
    public void foo() {
        // autonomous transport implementation
    }
}

public class Car implements Transport {
    private final Transport delegate;
    
    public Car(Transport delegate) {
        this.delegate delegate;
    }
    
    public void foo() {
        if(delegate == null)
            // car transport implementation
        else
            delegate.foo();
    }
    
}

P.S.这段代码向您展示了一个简短的解决方案。它可以是此模式的实现的许多变体。

比如说,不可能有一辆自动驾驶的火车。

考虑一下将inheritance替换为delegation。在大多数情况下,委派更可取。

选项2:没有严格的“自主运输”,而是让单个类根据需要继承(可能带有接口),如“汽车”、“自动汽车”、“卡车”、“自动卡车”。但不是一个有吸引力的选择,因为有4个以上的子类

在我看来,Autonomous Transport更像是behavior,而不是property。我确信,它不应该出现在Transport层次结构中。

选项3:可能,我可以使用依赖注入并在需要的地方注入“自主”功能,但我不能添加任何像dagger之类的框架。

Dipendency Injection是一种模式,但不是像Spring或Dagger那样的框架。如果您的类包含到另一个类的链接(通过构造函数或setter并不重要),实际上这已经是DI了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63747235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档