代码之家  ›  专栏  ›  技术社区  ›  JMS

隐藏派生C类中的属性

  •  3
  • JMS  · 技术社区  · 15 年前

    我有四个类,它们共享四个属性的某种排列。我当前已将基类设置为 abstract 每个属性标记为 virtual . 然后,在这四个派生类中的每一个中,我都将覆盖它使用的属性并忽略其他属性。

    问题是,无论是否已从 abstract virtual 我的基类中的属性。

    我有一种感觉,我从错误的角度来看待这个问题。是否有明确隐藏或阻止属性的方法,或者是否有更好的方法。

    5 回复  |  直到 15 年前
        1
  •  9
  •   Dzmitry Huba    15 年前

    我相信你应该重新考虑你的继承等级制度。考虑以下启发式方法:

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

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

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

        2
  •  2
  •   Beatles1692    15 年前

    恐怕无法隐藏派生类中的成员。(这违背了继承规则)要解决这个问题,可以有两个抽象类级别。在第一级中,有一个包含所有派生类中的所有成员的基类,在第二级中,可以有只包含您想要的成员的特殊类从这个类继承下来。

    //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;}
    }
    
        3
  •  1
  •   codymanix    15 年前

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

    可以重写属性以引发异常,但这不是一个好的设计。

    在一个类中,您应该只有在这个类中实际有效的成员。

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

        4
  •  1
  •   jolySoft    13 年前

    如果您不介意反射和投射,您可以使用助手方法尝试类似的方法。下面的示例假设订单有一个基类,但此处没有显示:

    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();
    

    一个朋友给我看了这个小图案,谢谢你的午睡。如我所说,它使用反射和投射,但可以使对象模型在处理基类时非常优雅。

        5
  •  0
  •   dbgrman    15 年前

    这里有一些规则在起作用。

    如果您有一个带有虚拟属性的抽象类,那么它们可以是受保护的,也可以是公共的,这就是外部世界将看到的。扩展/继承此类时,可以重写这些属性,但不能将它们标记为私有。私有是从派生类隐藏属性的唯一方法。在抽象类中拥有私有属性将使其对子类隐藏。但在你的场景中显然不是这样。