我有以下课程

  class GridBase
  {
    public object DataSource { get; set; }
  }

  class GenericGrid<T> : GridBase
  {
    public new T DataSource { get; set; }
  }


GridBase和Generic Grid类都可以实例化,也可以从任一类派生。

这是否被认为是实现这种层次结构的正确/可接受的方法?
还是应该多花点功夫像下面这样实现它

  class GridBase
  {
    protected object dataSource;
    public object DataSource { get { return dataSource; } set { dataSource = value; } }
  }

  class GenericGrid<T> : GridBase
  {
    public new T DataSource { get { return (T)dataSource; } set { dataSource = value; } }
  }


当在后代中重新引入属性时,同样适用于非通用类,我在这里仅使用通用示例。

另一个案例和问题

  abstract class SomeBase
  {
    protected abstract void DoSomething();
  }

  class Child : SomeBase
  {
    protected override void DoSomething()
    {
      /* Some implementation here */
    }
  }


这里的情况是框架“ X”声明了SomeBase,允许您定义自己的后代。他们创建的类(在运行时)然后从您的类(在这种情况下为Child)派生。但是,它们不会从DoSomething()的实现中调用您的DoSomething()方法。

他们不能盲目地调用base.Dosomething(),因为典型情况是它们生成的类通常是从SomeBase派生的,并且由于该方法是抽象的,所以无效。 (个人而言,我不喜欢C#中的这种行为)。

但是无论如何,这是一个好的或被接受的设计,没有调用base.xxx(),特别是当“意图”似乎矛盾时吗?

编辑从框架设计的角度。这样做是否可以/可以接受?如果不是这样,将如何设计它以防止发生这种情况或更好地传达其意图(在两种情况下)。

最佳答案

通用继承的第二种形式(广播基类的属性)更正确,因为它不违反Liskov Substitution Principle。可以想象,将通用类的实例转换为基类,并通过基类访问Data指向不同的属性。您将需要使两者保持同步,以使派生类可替代基类。

另外,您可以实现某种策略模式,其中基类从派生类中请求Data属性,以避免尴尬的向下转换。这就是我的想法:

public class Base {
  private readonly object m_Data; //immutable data, as per JaredPar suggestion that base class shouldn't be able to change it

  publlic Base(object data) {
    m_Data = data;
  }


  protected virtual object GetData() {return m_Data;}

  public Object DataSource {get {return GetData();}}
}

public class Derived<T> : Base {
  private T m_Data;

  public Derived():base(null){}
  protected override object GetData() {return m_Data;}

  protected new T Data {return m_Data;}
}


关于第二个问题,我注意到我已经理解了这个问题。听起来您遇到的问题是,框架在运行时生成代理时不调用抽象方法,这在抽象类中始终是合法的,因为该代码执行的唯一方法是必须通过重写的派生类抽象方法。

10-07 19:54
查看更多