代码之家  ›  专栏  ›  技术社区  ›  Mark A. Donohoe

从静态基类方法调用子类构造函数

  •  3
  • Mark A. Donohoe  · 技术社区  · 14 年前

    好 啊。。。在Objective C中,可以使用“new this()”从基类中的静态方法新建子类,因为在静态方法中,“this”指的是类,而不是实例。当我第一次发现它的时候,这是一个非常酷的发现,而且我经常使用它。

    然而,在C#中,这是行不通的。该死!

    像这样的。。。

    public class MyBaseClass{
    
        string name;
    
        public static Object GimmeOne(string name){
    
         // What would I replace 'this' with in C#?
            return new this(name); 
    
        }
    
        public MyBaseClass(string name){
            this.name = name;
        }
    
    }
    
    // No need to write redundant constructors
       public class SubClass1 : MyBaseClass{ }
       public class SubClass2 : MyBaseClass{ }
       public class SubClass3 : MyBaseClass{ }
    
    SubClass1 foo = SubClass1.GimmeOne("I am Foo");
    

    是的,我知道我可以(通常也会)直接使用构造函数,但是我们有一个特殊的需求,需要调用基类上的共享成员,所以这就是为什么我要问这个问题。再次,目标C让我来做这个。希望C也一样。

    2 回复  |  直到 11 年前
        1
  •  6
  •   Steve Michelotti    14 年前

    C#没有任何确切的等价物。但是,您可以通过使用以下泛型类型约束来解决此问题:

    public class MyBaseClass
    {
        public string Name { get; private set; }
    
        public static T GimmeOne<T>(string name) where T : MyBaseClass, new()
        {
            return new T() { Name = name };
        }
    
        protected MyBaseClass()
        {
        }
    
        protected MyBaseClass(string name)
        {
            this.Name = name;
        }
    }
    

    new()约束表示有一个无参数构造函数—您没有,但我们将其设为私有,以便对消费者隐藏它。然后可以这样调用:

    var foo = SubClass1.GimmeOne<SubClass1>("I am Foo");
    
        2
  •  0
  •   Adam Norberg    14 年前

    对不起,你不能这样做。C#在道德上反对静态方法继承。GimmeOne方法将永远不会有MyBaseClass以外的任何类型,从子类1调用它并不重要——它仍然是“真正的”MyBaseClass调用。反射库可以进行这种构造,但是除了MyBaseClass之外,您永远不会从中得到任何东西。

    如果您正在调用一个静态方法,那么您可能知道从哪个子类调用它。为每个子类创建不同的工厂方法。如果您真的试图通过实例来实现这一点,那么您可能应该使用非静态虚拟工厂方法(它将自动调用函数的最派生形式,这可能是您想要的)。