假設類A從繼承自類C的類B繼承。現在假設在A中定義了一個虛擬方法void f(),它在B和C中均被重寫。從任何方法調用Bf()在A中可以通過簡單地使用base.f()來完成。那麼從A中的方法調用C.f()怎麼樣?C#如何調用基地的基礎方法?
回答
通常,通過覆蓋一個類,您接受它提供了所需的接口和一些行爲。 A不應該知道它是超類,除非它的超類以某種方式明確暴露。這實際上是可取的,因爲當你繼承B時,你不需要知道C是如何實現的。你甚至不應該知道C涉及到了。如果b的f()調用base.f(),a的base.f()只需調用它自己的base.f(),就完成了。如果沒有,自己做的唯一方法就是通過基於反射的侵入式方法。如果你發現自己需要這樣做,那麼你的設計可能會出錯(違反德米特法則)。
謝謝,這不是我自己的設計。在這種情況下,B類和C類是Telerik組件。 B類提供了我所需要的大部分功能,但爲了實現我需要用C調用方法的一些功能。 – sisis 2010-04-02 18:17:42
試試這個:
C c = this;
c.f();
這版畫 「C」:
public static void Main()
{
A o = new A();
Console.WriteLine(o.f());
}
class C
{
public virtual string f()
{
return "C";
}
}
class B : C
{
public virtual string f()
{
return "B";
}
}
class A : B
{
public virtual string f()
{
C c = this;
return c.f();
}
}
這可以通過反射來完成。獲取當前類的Type,使用它獲取父類型,然後獲取父類型的父類型。
它不直接支持語言的原因是它打破了繼承的抽象模型。它與傳統的面向對象設計不兼容。
您可以通過反射或與IL代碼生成。除此之外,你不能,你真的不應該,這聽起來不像是好設計。
當您重寫OOP中的方法時,基本上說「對於此類型,此方法將替換舊方法」,並且可以根據需要(通常是此方法)調用替換的重寫)方法。
但是,您不能直接跳過關卡,除非您使用反射或IL欺騙,並且有一個很好的理由。如果中間類應該允許您跳過此方法調用,則應該爲其添加一個特殊的方法,以供您使用。這很難做到的原因是你通常不應該這樣做,你應該總是進入下一個階段,這樣才能保持控制。
我假設你的意思是從C中的方法調用A.f()。
簡短的回答:你不能
不過,如果你有超過B控制,你可以添加一個方法給B打電話給其基礎明確:
protected void BaseF()
{
base.f();
}
然後調用該方法從C
從C函數中,你可以調用base.f(),,這是你應該做的。如果B.f()(也就是你實際調用的內容)選擇調用base.f(),那麼它可以達到你想要的,但是完全取決於B的實現情況。
您可以嘗試鑄件C爲A和調用F(),像這樣:
public class C : B {
public override f() {
((A) this).f();
}
}
,但這樣做的問題是,C不知道其中f()聲明 - 它只知道在B中有一個可以被覆蓋的實現,C不知道A存在。上面的例子實際上是一段糟糕的代碼,如果A沒有實現f(),將會產生編譯時錯誤。
使用new
而不是override
是一種方式(該功能不需要是虛擬的即可使用new
)。
雖然這可能會給你一些其他問題。如果你將MyClass
上傳到MyBaseClass
任何地方,它將使用MyBaseClass
版本的功能。
private void Form1_Load(object sender, EventArgs e)
{
var mc = new MyClass();
mc.Foo();
((MyBaseClass) mc).Foo();
}
public class MyBaseClass
{
public virtual void Foo()
{
Console.WriteLine("Calling from MyBaseClass");
}
}
public class MyClass : MyBaseClass
{
new public void Foo()
{
Console.WriteLine("Calling from MyClass");
}
}
你得到的輸出是:
Calling from MyClass
Calling from MyBaseClass
正如前面的評論,虛擬永遠不能以這種方式被覆蓋,並且您必須使用「新」,而不是「覆蓋」。
下面是使用你的類名的例子:
這不是一個很好的做法,因爲它變得非常混亂,打破了很多預期的傳承行爲,以及「新」的關鍵字是爲了迫使新的接口項目放到不打算被覆蓋的類上。
乾杯, 傑森
class Program
{
static void Main(string[] args)
{
C c = new C();
A a = new A();
a.DoThis();
Console.ReadKey();
}
}
public class C
{
public virtual void DoThis() {
Console.WriteLine("In C"); }
}
public class B : C
{
public new void DoThis()
{
Console.WriteLine("In B");
}
}
public class A : B
{
public new void DoThis()
{
Console.WriteLine("In A..");
((C) this).DoThis();
}
}
這似乎是一個設計問題。
一對夫婦的選擇,您都:
- 拿大頭A.DoThis()的,並將其移動到另一種方法(保護?)叫適當的東西(找時間做()?)。現在,你可以直接調用它。
- 拆分你的對象,並考慮使用組合而不是繼承來重用行爲。
- 1. 調用方法的方法:Autorelease的基礎知識?
- 2. C++繼承,隱藏基礎方法
- 3. 只有基礎類方法?
- 4. 子類init方法只調用基礎初始化方法
- 5. 空軍基地的方法調用
- 6. 基礎Ruby練習 - 方法和如果
- 7. C++基礎知識
- 8. 在C++基礎類
- 9. 如何在基礎
- 10. 調用基類的方法
- 11. 基礎構造函數的Java調用庫方法
- 12. 從Child類C++調用基類方法
- 13. C#調用基方法與另一本
- 14. 如何調用基類方法?
- 15. 如何在地圖基礎上階
- 16. 如何從基類調用基類中的方法?
- 17. C++繼承 - 無法訪問的基礎?
- 18. 性能的方法審計基礎
- 19. 如何在C#中調用基重載的方法?
- 20. 如何從iOS自定義渲染器調用基礎Frame Renderer中的方法?
- 21. c中的基礎轉換
- 22. 二叉樹的C++基礎
- 23. 回到基礎。我如何回到C++?
- 24. 基礎關於IP地址
- 25. Objective C - 覆蓋基類的方法 - 如何調用子類的方法?
- 26. C#調用基於接口方法的方法
- 27. 如何在Objective-C中創建和調用基本方法?
- 28. 如何從C++派生類調用基類方法?
- 29. C++如何從多個派生類調用基類方法?
- 30. 如何輕鬆快速地學習c基礎?
可能的重複:http://stackoverflow.com/questions/1006530/c-how-to-call-a-second-level-base-class-method-like-base-base-gethashcode – itowlson 2009-12-04 00:32:56
我假設你的意思是從C中的方法調用Af()? – 2009-12-04 00:34:38
我真的只是猜測,但你不能把'this'給C嗎? ((C)這一點).F(); – 2009-12-04 00:46:17