2011-09-23 201 views
2

我可以这样做吗? (过于简单化了,因为它太复杂)C# - 继承,覆盖

abstract class A { 
    public string Print() {} 

    public static string DoPrint(A a, Type T) { 
    ((T)a).Print(); // <-- This should call eg. A3.Print(), not A.Print() 
    } 
} 

class A1: A { 
    public new string Print() {} 
} 

class A2: A { 

} 

class A3: A { 
    public new string Print() {} 
} 

class Somewhere 
{ 
    A3 a3 = new A3(); 
    a3.DoPrint(); 
} 

我有很多类(A1,A2,A3等),其从基类继承(A)

我试图创建上面的A类中的DoPrint()函数。 可以这样做吗?

我想这

public static string DoPrint(A a) { 
    a.Print(); 
    } 

但它调用A.Print(),而不是A3.Print()

编辑: “传递一个类型作为参数” 改了称呼从因为每个人都是对的,我可以使用虚拟(谢谢!)。这个问题在别的地方撒了谎,与这个问题无关。

+1

为什么你在'A1'等''Print'方法声明中指定'new'关键字?如果是关闭编译器警告,请将它们取出并考虑警告给出的建议。 –

+0

你不需要传递类型。只需使Print方法在所有类中都是虚拟的并且可以工作。 –

+4

为什么不让'Print'成为'virtual'方法?这就是'虚拟'的意义所在。 – Jon

回答

1

有什么不对正常的虚拟方法和继承?看看使用虚拟和覆盖:

abstract class A { 
public virtual string Print() {} 

    public static string DoPrint(A a) { 
    a.Print(); // <-- This WILL call eg. A3.Print(), not A.Print() 
    } 
} 

class A1 : A 
{ 
    public override string Print() {} 
} 

class A2 : A 
{ 
    public override string Print() {} 
} 
class A3 : A 
{ 
    public override string Print() {} 
} 
+0

对不起。并非所有类都需要重写Print()。你在这种情况下做什么? – Aximili

+0

如果不是所有类都需要重写Print,那么只需要在需要它的类中重写它,并在基类中提供基本实现。仍然没有理由不使用继承与我现在的信息... – jeroenh

1

基本上没有。你不能。除非你进入反思层面,并通过它找到并调用T定义的Print方法。任何类似接口或dynamic的应用程序都会选择最上面的实现。

但是,我不知道是否Print()这里应该是virtual

abstract class A { 
    public abstract string Print(); 
} 

class A1: A { 
    public override string Print() {} 
} 

class A2: A { 
    public override string Print() {} 
} 

class A3: A { 
    public override string Print() {} 
} 

并调用a.Print();。然后多态性将称为Print()的最衍生覆盖。

+0

对不起,并不是所有的类都会覆盖Print()。编辑的问题。这整个事情确实在各地都在使用Reflection。那么你如何“通过该方法调用T上定义的Print方法”呢?在这种情况下,最顶级的意味着A? – Aximili

3
public static string DoPrint(A a) { 
    a.Print(); 
} 

会工作,但您需要声明打印为虚拟并覆盖它。

abstract class A { 
     public virtual string Print() {} 

     public static string DoPrint(A a) { 
      a.Print(); 
     } 
    } 

    class A1: A { 
     public override string Print() {} 
    } 

    class A2: A { 
     public override string Print() {} 
    } 

    class A3: A { 
     public override string Print() {} 
    } 

    class Somewhere 
    { 
     A3 a3 = new A3(); 
     A.DoPrint(a3); 
    } 
+0

对不起,我只是意识到并不是所有的类都会覆盖Print()函数。这就是为什么它不是虚拟的。 – Aximili

+1

如果所有类都是虚拟的,则不需要覆盖它。 –

2

代替使用new,将基类的Print方法标记为虚拟,然后在子类方法声明中使用覆盖。

public virtual string Print() { } 

而在子类:

public override string Print() { } 
+0

对不起,我很粗心。并不是所有的类都会覆盖Print()。这就是为什么它不是虚拟的。 – Aximili

+2

@aximili - 并非所有课程都必须覆盖“打印”。一旦方法被标记为虚拟的,它是一个*可选的*覆盖。任何不会覆盖Print的类将使用由抽象树中的虚拟或上次覆盖提供的基线。 –

1

DoPrint()是一个静态函数。

你应该这样调用它:

A3.DoPrint(a3, typeof(A3));

A3.DoPrint(a3, a3.GetType());

现在,我不为什么你想这样做明白。为什么不简单地在类A中虚拟Print()并在派生类中重写它?