php - 根据里氏替换原则,子类是否允许拥有公共(public)方法?

标签 php oop inheritance solid-principles liskov-substitution-principle

考虑以下类层次结构:

Abstract class Printer{
    public print(){
        //code to handle printing
    }
}

class LaserPrinter extends Printer{
    private $file;
    public setFile($file){
        $this->file = $file; 
    }
}

class InkJetPrinter extends Printer{
    private $document;
    public setDocument($document){
        $this->document= $document; 
    }
}

class ClientClass{
    private $filesToPrint=array();
    public __construct(InkJetPrinter $inkJetPrinter, LaserPrinter $laserPrinter){   //I was hoping to apply Dependency Inversion here by defining both inputs as type Printer instead
         //constructor stuff    
    }

    public function startPrinting(){
         //some logic to extract the $files and $documents from $this->filesToPrint
         //...
         $this->inkJetPrinter->setDocument($document);//<---Things got messy here
         $this->laserPrinter->setFile($file);//<---and here too
         //...
    }
}

现在类 LaserPrinter 无法被其父类 Printer 替换,因为 Printer 没有 setFile > 方法。
这是否意味着他的等级制度打破了里氏替换原则?子类不允许有自己的公共(public)方法吗?

最佳答案

首先,我假设您在该代码中具有继承,尽管我看不到任何暗示 LaserPrinter 或 InkJetPrinter 从 Printer 继承的信息。

不,它不会违反里氏原则,因为子类在用作打印机时需要正确运行。

可能引发您问题的一点是,这些类还应该使用依赖反转,因此完整构建的 LaserPrinter 应该传递给任何使用打印机的东西。在您的示例中,创建 LaserPrinter 后文件可以更改吗?

如果文件不需要更改,那么您可能希望将其传递到 LaserPrinter 的构造函数中。如果文件可以更改,那么您需要:在 LaserPrinter 中创建文件名或创建一个新类来创建文件名,然后将该类注入(inject) LaserPrinter 中。

您可能想了解 Open/ClosedDependency Inversion原则,因为我认为它们与你的问题密切相关。


编辑

再次查看代码后,我发现有一些奇怪的地方。 Printer.print() 应该接收一个描述打印内容的参数。让 LaserPrinterInkJetPrinter 引用它们需要从实例变量打印的内容看起来是错误的。

例如,您不会说:打印机,这里有一个文档...现在打印它

它更像是打印机,现在您已完全配置并运行,打印此文档

看起来您已经有了一个代表您要打印的内容的对象(封装了文档和文件)。您可以传递该对象并获得类似 print(jobDetail) 的内容。

关于php - 根据里氏替换原则,子类是否允许拥有公共(public)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12942903/

相关文章:

php - 制作自动换行。 PHP 到 Excel

c# - 结构是否可以序列化

c# - 继承问题,从继承类的某些数据上获取 NULL

javascript - 页面加载完成后隐藏加载图像

javascript - 使用 JavaScript 框架进行服务器端渲染 : What are the benefits over established backend-technologies?

c++ 重载 < 在 C++ 中对多个类使用友元函数?

c++ - 在 OOP 中,什么是转发,它与委托(delegate)有何不同?

c++ - ‘<’ token 错误之前的 GCC 预期模板名称

c# - 从继承另一个的类中获取变量

PHP MySql (1045) 用户访问被拒绝