我有一个应用程序,其中许多对象都扩展了一个抽象类,它定义了create()
edit()
retrieve()
和delete()
等方法。由于每个子类对这些函数使用相同的逻辑,因此抽象类定义了默认行为,并且在需要扩充的少数情况下,子类可以覆盖或使用我内置的钩子。 / p>
现在我遇到的情况是某些子类需要变成不可变的,这意味着它们不应该有edit()
或delete()
方法。这个需求听起来像是一个名为immutable
的接口的作业,不可变类可以实现。问题是接口不会阻止方法被调用,它们只是强制实现方法的存在。所以这显然无法发挥作用。
创建两个父类,一个用于可变对象,一个用于不可变对象,这很难看,并且可能会在维护时询问问题。我可以让不可变对象用一个没有做任何事情的空方法覆盖有问题的方法,但这看起来也很混乱,就像我当时没有做正确的OOP。
那么你会建议什么是允许大量类继承一组方法的最佳方法,但是对于其中一些方法不能继承所有方法? (有问题的应用程序是用PHP编写的,但是任何语言的一般OOP技术仍然有用)。
答案 0 :(得分:3)
创建一个不可变基类作为基类的子类。 immutable-base应该实现edit()和delete()的final覆盖,它们不执行任何操作或抛出错误。
最后,以确保所有不可变的孩子都无法编辑或删除
此策略的奖金
通过测试instanceof immutable-base轻松检查对象是否不可变
通过修改扩展的内容,轻松地从不可变对象和后退对象
答案 1 :(得分:2)
实际上创建具有空方法或抛出错误的类是不好的 - 这样的方法令人困惑,它们占用空间而什么都不做。
更好的方法是使不可变类成为基类,并使可变类通过添加修改方法来扩展它。这样每个类只有那些真正属于那里的方法。
答案 2 :(得分:0)
我喜欢Java的方法。抛出一个例外。创建一个UnsupportedOperationException
,对于那些不应该使用特定方法的实现,抛出一个让用户知道他们不能将此功能用于此实现。
答案 3 :(得分:0)
另一种想法,我想抛出一个可能的解决方案。类可以实现如下所示的接口:
Interface Immutable {
const immutable = true;
}
然后Base抽象类可以用
编写delete()
和edit()
方法
if (!$this->immutable) {
//do_stuff
}
这也可以很好地扩展到其他类的分类,比如NonDeletable和NonEditable,以允许更细粒度的行为。
答案 4 :(得分:0)
这是超短的解决方法,让你的方法最终并以:
开始 if(self::class!=static::class) return;#or throw an error
它不会阻止继承本身,但是方法在子类中不起作用(有错误或没有 - 取决于你)。
答案 5 :(得分:0)
从PHP 5.4开始,您可以使用Traits。
例如,您可以创建一个仅包含所有子类所具有的方法的基类:
class EntityManager {
public function create() {/*...*/}
public function retrieve() {/*...*/}
}
然后你可以定义几个特征:
trait EditTrait {
public function edit() {/*...*/}
}
trait DeleteTrait {
public function delete() {/*...*/}
}
然后,您将创建一个不可变的子类,如下所示:
class LogManager extends EntityManager {
...
}
这是一个可变的子类:
class ContactManager extends EntityManager {
use EditTrait;
use DeleteTrait;
...
}
Traits比其他一些解决方案有一些优势,例如: