我想知道构造类的最佳实践,以便在类具有祖父母时调用父方法。
假设我有这种情况:
public class Vehicle { // parent
public bool moves;
public bool flies;
public float maxSpeed;
public virtual void Initialize () {
moves = true;
}
}
public class Airplane : Vehicle { // child
public override void Initialize () {
base.Initialize ();
flies = true;
}
}
public class Jet : Airplane { // grandchild
public override void Initialize () {
base.Initialize ();
maxSpeed = 400f;
}
}
现在,如果我实例化一个Jet对象,它将运行Vehicle初始化,但不是飞机父代码(意味着它不会飞)。
这有一些解决方法。一个是将飞机代码移动到每个子类,但它失败了使用OOP的目的。解决这个问题的最佳做法是什么?
注意:我不能使用构造函数,因为这是一个Unity3D应用程序,并且附加到GameObject的所有类都应该继承自MonoBehaviour类,并且它有自己的初始化函数,如Awake()和启动(),不允许构造函数。
答案 0 :(得分:6)
我想知道构造类的最佳实践,以便在类具有祖父母时调用父方法。
你不这样做。
问题的假设是从飞机派生的Jet需要知道飞机从车辆派生的实施细节。这是一个糟糕的假设。最佳做法是将飞机视为黑匣子(没有双关语),而不利用其实施细节的知识。
您的Initialize方法有一个合同:它初始化了一些东西。如果你想要它被调用,你可以调用它。它负责确保其不变量得到满足;让它做它的工作。
现在,在这个特定的案例中,您不能任何。你没有写一个初始化方法,你肯定不会打电话给基地。如果您想要字段初始值设定项,那么就可以编写字段初始值设定项。
class Vehicle { protected bool moves = true; }
class Airplane : Vehicle { protected bool flies = true; }
class Jet : Airplane { protected double speed = 400; }
让我们考虑一个更好的例子。假设我们有一个可以重绘的显示表面:
interface IUserInterface { void Redraw(); }
现在我们可以提出一个规则所在的层次结构:当你重新绘制时,你还必须调用你的超类:
abstract class ControlWithChildren : IUserInterface
{
...
protected IEnumerable<IUserInterface> children;
public virtual void Redraw() {
foreach(var child in children) child.Redraw();
}
class Panel : ControlWithChildren
{
...
public override void Redraw()
{
... redraw panel elements ...
base.Redraw();
}
}
class PanelWithTitle : Panel
{
...
public override void Redraw()
{
... redraw title element ...
base.Redraw();
}
}
你去吧。 PanelWithTitle只处理重新绘制标题,并将其余工作推迟到Panel。 Panel重新绘制面板背景,并将其余工作推迟到ControlWithChildren。 PanelWithTitle无需了解ControlWithChildren的重绘语义。如果它确实需要知道,那么 Panel 的实现就会出现问题。
答案 1 :(得分:-2)
我会创建接口并远离继承。改用构图。换句话说,make Jet包含Airplane和Vehicle类(我假设Jet具有飞机没有的特殊能力或属性)。并使用委托方法。
它使您的项目不那么脆弱。换句话说,如果你改变你的基类,你必须担心你的孩子(甚至可能是曾孙子)如何处理它。但是,如果包含它,只要接口相同,容器类就不会关心。
这并不是要破坏OOP的目的,而是更好的使用方式。我们仍然有那些单独的对象,而不是复制粘贴代码。但是,我们正在取消继承的使用。
我建议你阅读这篇以星球大战为主题的娱乐博客文章。 * http://blog.berniesumption.com/software/inheritance-is-evil-and-must-be-destroyed/
如果那不是你的事情只是谷歌“构成过继承”并享受火焰战争。