简体   繁体   English

从抽象基类的具体类中重写C#模板方法

[英]C# Template method override in concrete class from abstract base class

I have the following code which has a Base class containing an abstract template method, which in the derived classes is overridden using concrete types. 我有以下代码,其中的Base类包含抽象模板方法,该类在派生类中使用具体类型覆盖。

class MyObj
{
   private string name;
   public string Name { get; set; }
};

class MyObj2
{
  private string value
  public string Value { get; set; }
}

abstract class Base
{
  public abstract string toString<T>(T t);
  public void doSomething<T>(T t)
  {
    string myValue = toString<T)(t);
    ...
  }
};

class MyClass : Base
{
  public override string toString<MyObj>(MyObj o)
  {
     return o.Name;
  }
}

class MyClass2 : Base
{
  public override string toString<MyObj2>(MyObj2 o)
  {
     return o.Value;
  }
}

But the compiler doesn't like the implementations of toString() in MyClass or MyClass2 , giving an error message along the lines of: 但是编译器不喜欢MyClassMyClass2toString()的实现,它给出以下错误消息:

'MyObj' does not contain a definition for 'Name' and no extension method 'MyObj' accepting a first argument of type 'MyObj' could be found (are you missing a using directive or an assembly reference?) 'MyObj'不包含'Name'的定义,找不到可以接受类型为'MyObj'的第一个参数的扩展方法'MyObj'(您是否缺少using指令或程序集引用?)

You appear to be trying to provide an implementation for one specific type argument. 您似乎正在尝试为一种特定类型的参数提供实现。 You can't do that, and it doesn't make sense - it's not clear what would happen if the caller passed in a different type argument, eg 您无法做到这一点,而且没有任何意义-不清楚如果调用方传入其他类型的参数(例如,

Base b = new MyClass2();
b.doSomething<int>(10);

(At the moment, your MyObj and MyObj2 in the methods are being treated as type parameters rather than as the types themselves, which is why the compiler doesn't know anything about your Name or Value properties.) (目前,方法中的MyObjMyObj2被视为类型参数,而不是类型本身,这就是为什么编译器对NameValue属性一无所知的原因。)

It sounds like really it should be the class which is generic: 听起来确实应该是泛型的

abstract class Base<T>
{
  public abstract string ToString(T t);
  public void DoSomething(T t)
  {
    string myValue = ToString(t);
    ...
  }
}

class MyClass : Base<MyObj>
{
  public override string ToString(MyObj o)
  {
     return o.Name;
  }
}

class MyClass2 : Base<MyObj2>
{
  public override string ToString(MyObj2 o)
  {
     return o.Value;
  }
}

At this point, the previously-problematic code wouldn't work, because you'd to use Base<MyObj2> as the variable type instead of just Base , and you could only pass a MyObj to DoSomething . 在这一点上,以前有问题的代码将无法工作,因为您将使用Base<MyObj2>作为变量类型,而不是仅使用Base ,并且只能将MyObj传递给DoSomething

(You might also want to consider making the ToString method protected instead of public. That's more common for the template method pattern, although certainly not required.) (您可能还想考虑将ToString方法设置为受保护的而不是公共的。这对于模板方法模式更为常见,尽管当然不是必需的。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM