.NET继承:从基类中屏蔽一个属性

8
考虑Employee(员工)、Manager(经理)和Assistant(助手)类:

public class Emp
{
    public string Name { get; set; }
    public Manager Manager { get; set; }
    public Assistant Assistant { get; set; }
}

public class Manager : Emp
{ 
}

public class Assistant : Emp
{
}

目标是禁止一段代码像这样访问属性:
var foo = new Manager();
var elmo = new Emp();
elmo.Manager = foo;
elmo.Manager.Manager = new Manager(); 
//how to disallow access to Manager.Manager ?

因为Manager继承自Emp,所以它有.Manager.Assistant属性。
问题:
.NET的继承实现中是否有修饰符可以删除.Manager.Assistant属性?
更新:
非常感谢大家的回答。我希望通过简化和刻意设计的Emp/Mgr能够在这个问题中体现出来。很明显,在这个例子中,继承应该被转换成另一个共性(例如Person,其中类会共享姓名、出生日期等)。非常感谢您的回答!

这对我来说似乎是一个设计问题。虽然经理可能向另一位经理汇报,但助手可能没有助手。也许基础应该是“人”... - Walter
6个回答

9
这样做会违反Liskov替换原则,通常表明设计有问题。一般来说,任何子类都应该能够在基类可以使用的任何上下文中使用。如果Manager没有.Manager,那么它们不是Emp,也不应该继承自它们。

5
不行 - 因为这会违反Liskov替换原则。基本上,你可以添加东西,但不能删除它们。
你可能会在执行时覆盖属性以抛出异常,但无法在编译时执行此操作。
通常,如果您想禁止此类事情,应考虑组合而不是继承,因为您没有真正的继承关系。

2

不,没有。

你可以将基类属性设置为virtual,然后在setter中重写它以抛出异常,但无法提供编译时错误。毕竟,在编译时没有任何操作可以防止这种情况发生。

(elmo.Manager as Employee).Manager = new Manager();

但是,您可以编写

public class ManagerEmployee : Emp {     
    public new ManagerEmployee Manager { 
        get { return base.Manager; }
    }
}

请注意,这并不能防止强制类型转换。

1

像大多数事情一样,这取决于情况。给定以下类:

public class foo
{
    public string Test { get { return "foo"; } } 
}

public class bar : foo
{
    public new string Test { get { return "bar"; } }
}

以下是代码:

        bar a = new bar();
        // returns bar
        literalTest1.Text = a.Test;

        foo b = new foo();
        // returns "foo"
        literalTest2.Text = b.Test;

        foo c = new bar();
        // returns "foo"
        literalTest3.Text = c.Test;

根据上面的评论,你可以看到,即使属性没有声明为虚拟的,你也可以重写它。然而,只有在对象变量被声明为覆盖该属性的类型时,才会使用重写的属性 - 而不是任何其祖先类。这实际上破坏了多态性。
改正你的祖先类。

0

正如其他人所说。不行。我要补充的是,如果并非每个员工都有一个经理和一个助手,那么你的继承层次结构就是错误的。似乎员工和经理唯一共享的是名字。你可以通过继承添加,但不能通过继承删除。


0

不,你不能这样做,也不应该这样做——经理既是员工,又有经理和助手,或者没有,因此应该有一个不同的基类,即这种情况表明设计存在缺陷。一种可能性是对于这些属性返回 null,如果在领域上有意义的话。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接