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

是否可以在C中为仿制药制作“这种类型”?

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

    有点理论问题。很长时间了,如果你不喜欢理论的话,可以随意跳过。

    假设您有两个类,一个继承自另一个类。基类是泛型的,并且具有一个方法,该方法在封闭类型中必须返回此封闭类型的某个实例。

    像这样(音符) ???? 在文本中):

    public class Adapter<T>
    {
     public virtual ??? DoSomething()
     {
      ...
     }
    }
    
    public class AdaptedString : Adapter<String>
    {
     public override AdaptedString DoSomething()
     {
      ...
     }
    }
    

    我不能这样做,因为无法引用将从泛型类型派生的封闭类型。(对不起,语言有问题,只是不知道怎么表达)没有关键字可以代替 ??? 指定此方法将返回将从此泛型类型派生的类型的实例。

    相反,我可以使用将类型名显式传递给泛型基的变通方法。但这看起来是多余的。

    public class Adapter<TThis,T>
    {
     public virtual TThis DoSomething()
     {
      ...
     }
    }
    
    public class AdaptedString : Adapter<AdaptedString,String>
    {
     public override AdaptedString DoSomething()
     {
      ...
     }
    }
    

    如果在基类中,我需要访问 TThis 例如,我必须添加一个约束。这次看起来很难看-注意限制:

    public class Adapter<TThis,T>
     where TThis : Adapter<TThis, T>
    {
     protected int _field; 
    
     ...
    
     public bool Compare( TThis obj )
     {
      return _field == obj._field;
     }
    }
    
    public class AdaptedString : Adapter<AdaptedString,String>
    {
     ...
    }
    

    是的,一切正常,但如果我能简单地使用一些关键字而不是 ???? 在第一个代码片段中。有点像” 蓟马 “。

    你认为它会怎样工作?有用吗?或者这只是一个简单的愚蠢?

    4 回复  |  直到 15 年前
        1
  •  10
  •   Jon Skeet    15 年前

    没有什么能使这个模式更简单,而且事实上,这个模式并不是完全防弹的-因为你可以:

    class TypeA : Adapter<TypeA, string>
    
    class TypeB : Adapter<TypeA, string> // Bug!
    

    第二条是完全合法的- TypeA 是的有效类型参数 TThis 类型参数,即使它不是我们想要的。基本上类型系统不允许我们表达“t必须是这个类型”的概念。

    不过,我不同意那些说这是一种糟糕或无用的模式的人。我发现它在 Protocol Buffers -那会是 许多的 没有它更糟。例如:

    Foo foo = new Foo.Builder { Name="Jon" }.Build();
    

    如果 Foo.Build() 不是强类型返回的 Foo 即使 Build 方法在中指定 IBuilder<...> .

    如果你容易的话,这是值得避免的。 可以 只是因为它变得如此复杂-但我认为这是一个有用的模式。

        2
  •  5
  •   Reed Copsey    15 年前

    在这种情况下,通常只需要引用基类:

    public class Adapter<T> { 
       public virtual Adapter<T> DoSomething();
    

    试图做你正在做的事违反了 Liskov substitution principal .

        3
  •  -1
  •   David R Tribble    15 年前

    如果派生类中的继承方法需要返回派生类型而不是基类型(称为 covariant return type ,这在C中已经得到支持。

        4
  •  -1
  •   Dusda    15 年前

    我也很难为这个找到一个可以论证的用例(尽管这是一个有趣的想法)。

    您是否试图改变您如何约束可以使用的泛型类型?听起来你很想 假设一些基本功能,而不知道实际类型;这就是接口的用途 . WHERE子句对于这些问题非常方便。

    class Dictionary<K, V>
    where K : IComparable, IEnumerable
    where V : IMyInterface
    {
        public void Add(K key, V val)
        {
        }
    }
    

    上面的示例约束k(键),使其具有可比性和可枚举性,v必须通过自己的接口实现您想要的任何客户功能。