假設類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. 基礎對象沒有方法基礎
- 2. 如何找到簡單的方法在C#Windows基礎應用
- 3. 調用方法的方法:Autorelease的基礎知識?
- 4. C++繼承,隱藏基礎方法
- 5. 只有基礎類方法?
- 6. 子類init方法只調用基礎初始化方法
- 7. 空軍基地的方法調用
- 8. 無法調用抽象基礎成員
- 9. 基地64基礎上的對話
- 10. 基礎Ruby練習 - 方法和如果
- 11. C++基礎知識
- 12. 在C++基礎類
- 13. C#基礎程序
- 14. C語言基礎
- 15. 如何在基礎
- 16. 使用虛擬方法調用基礎(使用Java)
- 17. 調用基類的方法
- 18. 從基類C++調用虛擬方法
- 19. C#調用基方法與另一本
- 20. 從Child類C++調用基類方法
- 21. 基礎構造函數的Java調用庫方法
- 22. 循環基礎的調度算法
- 23. 如何調用基類方法?
- 24. 如何在地圖基礎上階
- 25. 核心基礎VS基礎或核心基礎+基金會
- 26. 如何從基類調用基類中的方法?
- 27. 從基類調用基類方法
- 28. C++繼承 - 無法訪問的基礎?
- 29. 性能的方法審計基礎
- 30. Fortran語法基礎?
可能的重複: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