我有四个课程,分享四个属性的一些安排。我目前将基类设置为abstract
,每个属性都标记为virtual
。然后在四个派生类中的每一个中,我将覆盖它使用的属性并忽略其他属性。
问题是我仍然可以访问每个派生类中的所有属性,无论我是否从我的基类中的abstract virtual
属性覆盖它。
我感觉我从错误的角度接近这个。有没有办法明确隐藏或阻止属性,或者是否有更好的方法。
答案 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是从派生类隐藏属性的唯一方法。在抽象类中拥有私有属性会将其隐藏在子级中。但在您的方案中显然不是这种情况。