2010-01-13 58 views
6

有没有办法做什么classmethod在Python在Python中做的?C#的Python风格的classmethod?

也就是说,一个静态函数将根据使用的任何子类将Type对象作为(隐式)参数。

的我想要的一个例子,大约是

class Base: 
    @classmethod 
    def get(cls, id): 
     print "Would instantiate a new %r with ID %d."%(cls, id) 

class Puppy(Base): 
    pass 

class Kitten(Base): 
    pass 

p = Puppy.get(1) 
k = Kitten.get(1) 

预期的输出是

Would instantiate a new <class __main__.Puppy at 0x403533ec> with ID 1. 
Would instantiate a new <class __main__.Kitten at 0x4035341c> with ID 1. 

(same code on codepad here.)

回答

1

原则上,你可以是这样的:

class Base 
{ 
    public static T Get<T>(int id) 
     where T : Base, new() 
    { 
     return new T() { ID = id }; 
    } 

    public int ID { get; set; } 
} 

然后,你可以写var p = Base.Get<Puppy>(10)。或者,如果你感到受虐狂,你可以写Puppy.Get<Puppy>(10),甚至Kitty.Get<Puppy>;)在所有情况下,你必须明确地传递类型,而不是隐含的。

或者,这也工作:

class Base<T> where T : Base<T>, new() 
{ 
    public static T Get(int id) 
    { 
     return new T() { ID = id }; 
    } 

    public int ID { get; set; } 
} 

class Puppy : Base<Puppy> 
{ 
} 

class Kitten : Base<Kitten> 
{ 
} 

您仍然需要通过类型备份到基类,它允许你写Puppy.Get(10)预期。

但是,仍然有这样写的原因,当var p = new Puppy(10)是一样简洁和更习惯?可能不会。

2

根据上下文,你要么需要仿制药或虚拟方法。

0

这相当于Object Pascal中的类方法。 (.Net实现将是RemObject的oxygene)。

但是,虽然在原始平台上有类引用,因此虚拟类方法或看似静态方法可以访问某些类级别的状态,但我认为它们对于.Net或C#没有多大意义。

我以前也在Oxygene中编程了好几年,而且我从不需要类的引用。

不是因为我不知道如何使用它们。在“原始”ObjectPascal平台上,原生Delphi,我用它们全部为的时候。但是因为.Net和BCL没有真正的支持它们,所以使用它们没有任何优势。而像Python或原生Delphi这样的平台确实在他们的库中支持它们。

你显然不想要一个静态方法,你想要的是可以有状态和/或支持继承的东西。所以无论是工厂,还是你的构造函数都可能会很好。

0

因为C#是静态编译的,所以在编译时调用Puppy.get(),例如。已知指向Base.get(),这意味着生成的CIL(公共中间语言)将有一个呼叫指令到Base.get()

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  9 (0x9) 
    .maxstack 8 
    IL_0000: nop 
    IL_0001: ldc.i4.1 
    IL_0002: call  void Base::get(int32) 
    IL_0007: nop 
    IL_0008: ret 
}