在派生的C#类中隐藏属性

时间:2009-09-13 11:33:58

标签: c# asp.net oop inheritance

我有四个课程,分享四个属性的一些安排。我目前将基类设置为abstract,每个属性都标记为virtual。然后在四个派生类中的每一个中,我将覆盖它使用的属性并忽略其他属性。

问题是我仍然可以访问每个派生类中的所有属性,无论我是否从我的基类中的abstract virtual属性覆盖它。

我感觉我从错误的角度接近这个。有没有办法明确隐藏或阻止属性,或者是否有更好的方法。

5 个答案:

答案 0 :(得分:9)

我相信你应该重新考虑你的继承层次结构。请考虑以下启发式方法:

如果两个或多个类只共享公共数据(没有共同行为),则应将该公共数据放在将由每个共享类包含的类中。

如果两个或多个类具有共同的数据和行为(即方法),那么这些类应该都从一个捕获这些数据和方法的公共基类继承。

如果两个或多个类只共享一个公共接口(即消息,而不是方法),那么只有当它们以多态方式使用时,它们才应该从公共基类继承。

答案 1 :(得分:2)

我担心不可能在派生类中隐藏成员。(这违反了继承规则)要解决这个问题,你可以有两个级别的抽象类。在第一级有一个基类,所有成员都是应该在所有派生类中,在第二级,您可以拥有特殊类,只有您希望从此类继承的成员。

//Level1
public abstract class Employee
{
public string Name{get;set;}
public abstract double CalculateSalary();

}

//Level2
public abstract class CalssAEmployee:Employee
{
public int NumberOfWorkingHours{get;set;}

}

public abstract class ClassBEmployee:Employee
{
public int NumberOfSales{get;set;}
}

答案 2 :(得分:1)

您无法删除/隐藏派生类中的方法或属性,因为这与liskov的替换原则相矛盾。

您可以覆盖属性以抛出异常,但这不是一个好的设计。

你应该只在一个班级中拥有在这个班级上实际有效的成员。

也许你想要定义几个具有属性的接口,让每个类实现你需要的接口。

答案 3 :(得分:1)

如果你不介意反思和投射,你可以尝试使用辅助方法。下面的示例假设Orders有一个基类,这里没有显示:

public abstract class Client : Entity
{
    public virtual string Name { get; set; }
    public virtual string  Comments { get; set; }
    public virtual string  Requirement { get; set; }
    public virtual string  Complaints { get; set; }
 }

public class GreatClient : Client
{
    public virtual List<GreatOrder>  Orders { get; set; }
}

public class WebClient : Client
{
    public virtual List<BadOrder> Orders { get; set; }
}

public static class ClientHelper
{
    public static IEnumerable<Order> GetOrders(this Client client)
    {
        var result = new Dictionary<Type, Func<Client>>
                         {
                             {typeof (GreatClient), () => { return ((GreatClient) client).Orders;}},
                             {typeof (WebClient), ()=> { return ((WebClient) client).Orders;}}
                         };

        return result[dto.GetType()].Invoke();
    }
}

//Client code
Client client = new WebClient();
client.GetOrders();

朋友告诉我这个小模式,谢谢Nap。就像我说它使用反射和转换一样,但在处理基类时可以使对象模型非常优雅。

答案 4 :(得分:0)

这里有几条规则。

如果您有一个具有虚拟属性的抽象类,它们可以受到保护或公开,这是外部世界将看到的。扩展/继承此类时,可以覆盖这些属性,但不能将它们标记为私有。 Private是从派生类隐藏属性的唯一方法。在抽象类中拥有私有属性会将其隐藏在子级中。但在您的方案中显然不是这种情况。