混合使用子类型和重写是不好的做法吗?

问题描述 投票:0回答:1

请纠正我此帖子中的任何陈述是错误的。

我读到,恢复代码是继承的主要好处,但我突然意识到,通过子类型实现的多态性是继承的主要优点,并且使得在复杂系统中重用代码成为可能。

在网上的许多文章中,我看到子类型不断与多态性结合在一起。我理解 SubTyping 是在继承模式中实现重写的一种手段。虽然,两者都是不同形式的多态性。

以下代码链接为例:

class Logger
{
    public void count(string filepath) {
        Writeline("I'm counting lines of %s pretty hard!\n", $filepath);
    }
}

class JSONLogger extends Logger {
    public override void count(string filepath) {
        Writeline("I'm counting JSON objects from file %s pretty hard!\n", $filepath);
    }
}

class Shipment
{
    private Logger logger;

    public Shipment (Logger logger) {
        this.logger = logger;
    }

    public void count(string filepath) {
        this.logger.count(filepath);
    }
}

shipment = new Shipment(new JSONLogger());
shipment.count("/my/shipment");

这里我们使用 Logger 的一个子类型,即 JSON Logger 来重写 count 方法。

但是 SubTyping 是否应该与 Overrding 一起使用?混合重写和子类型不是很糟糕吗?

例如,想要创建Shipment实例的用户需要了解Logger对我们来说是什么?常规记录器还是 JSONLogger?

用户需要查看这两个记录器是如何实现的,以决定他需要使用哪种行为。但这不是违反了抽象原则吗?

我们创建对象和抽象行为,因此我们不需要担心它们是如何实现的。如果上面的代码是一个更复杂的继承树,具有更多的类和更多的重写,那么我们需要知道所有这些额外信息,例如子类如何重写超类行为以及超类本身是否重写任何基类行为等。

在这种情况下,在运行时动态实现 SubTyping 或 Substitute 对象实际上不是很困难吗?

那么,混合重写和子类型是不是很糟糕?或者重写一般只是糟糕的设计?

oop design-patterns computer-science software-design design-principles
1个回答
0
投票

我认为您问了错误的问题并使用了错误的术语。重写实际上是指在子类中重新实现超类方法的行为,这实际上很常见。没有比继承本身更固有的问题了。但是,如果您在没有 super 调用的情况下重写所有方法,那么继承就变得毫无意义,因为没有继承的行为。在上面的示例中,

Logger
很可能是一个接口而不是一个类,并且您将有该接口的 2 个具体实现。

这里我们使用 Logger 的一个子类型,即 JSON Logger 来重写 count 方法。

这不是覆盖。将实现委托给注入的协作者被称为策略模式,它是最广泛使用的设计模式之一。

例如,想要创建Shipment实例的用户需要了解Logger对我们来说是什么?常规记录器还是 JSONLogger?

很多时候,客户实际上希望控制策略。例如,当您在java(排序集)中创建

TreeSet
时,您可以传递一个
Comparator
用于自定义排序。然而,在某些情况下,您希望让客户免于明确地做出此类决定,并且您可以使用“创建模式”之一抽象出创建过程的这一部分。 顺便说一句,我知道你的例子很可能不是取自现实世界,但设计的问题似乎是

Shipment

有太多的责任,并且在错误的抽象级别与协作者合作。

    

© www.soinside.com 2019 - 2024. All rights reserved.