考虑以下类层次结构:
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/Closed和 Dependency Inversion原则,因为我认为它们与你的问题密切相关。
编辑
再次查看代码后,我发现有一些奇怪的地方。 Printer.print()
应该接收一个描述打印内容的参数。让 LaserPrinter
或 InkJetPrinter
引用它们需要从实例变量打印的内容看起来是错误的。
例如,您不会说:打印机,这里有一个文档...现在打印它。
它更像是打印机,现在您已完全配置并运行,打印此文档
看起来您已经有了一个代表您要打印的内容的对象(封装了文档和文件)。您可以传递该对象并获得类似 print(jobDetail)
的内容。
关于php - 根据里氏替换原则,子类是否允许拥有公共(public)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12942903/