代码之家  ›  专栏  ›  技术社区  ›  Sergey Khachaturov

当使用“Builder”模式时,在非泛型方法中,我如何才能将返回对象inself(this)作为其确切类的实例(无需强制转换)

  •  0
  • Sergey Khachaturov  · 技术社区  · 1 年前

    全能者!

    我正在开发一些Builder,使用“Builder”模式。
    基类有一个返回自身的方法“SomeMethod”,该方法可以在构建过程中的调用链中使用,如以下所示:MyBuilderClassObject。SomeMethod()。其他方法()。。。

    SomeMethod是虚拟的,可以在子类中覆盖,但不能覆盖。
    所以它必须返回“this”作为基类的实例。
    问题是“OtherMethod”只存在于一个子代中,但SomeMethod()的结果是Base,并且它没有“OtherMethod

    public abstract class Base
    {
        public virtual Base SomeMethod()
        {
            return this;
        }
    }
    
    public class Derived1 : Base
    {
        public void OtherMethod()
        {
            ;
        }
    }
    
    public class Derived2 : Base
    {
        public void AnotherOneMethod()
        {
            ;
        }
    }
    

    我想这样使用它:

    var d1 = new Derived1();
    d1.SomeMethod().OtherMethod(); // CS1061 'Base' does not contain a definition for 'OtherMethod'
    
    var d2 = new Derived2();
    d2.SomeMethod().AnotherMethod(); // CS1061 'Base' does not contain a definition for 'AnotherMethod'
    
    • 我知道我能演:
      ((Derived1)d1.SomeMethod()).OtherMethod() 但是当链条很长的时候,它太无聊和丑陋了

    • 我知道我可以对SomeMethod使用泛型,并将其称为:
      d1.SomeMethod<Deriver1>().OtherMethod()
      但它也很愚蠢,因为在Derived1实例上调用的SomeMethod的concret类型是显而易见的

    • 我知道我会打破链条:
      d1 = new Derived1(); d1.SomeMethod(); d1.OtherMethod(); 但这违反了Builder模式的思想

    • 我试图挖掘协变和逆变接口,但没有成功。

    更新:
    对我来说,这似乎是一个解决方案(可能不是最漂亮的,但有效):

    public abstract class Base<T> where T : Base<T>
    {
        public virtual T SomeMethod()
        {
            return this as T;
        }
    }
    
    public class Derived : Base<Derived>
    {
        public void OtherMethod()
        {
            ;
        }
    }
    
    // using:
    var d1 = new Derived1();
    d1.SomeMethod().OtherMethod();
    

    UPD2:不,当继承链长于1(对于 class Derived2: Derived1 ) :(

    0 回复  |  直到 1 年前