2013-07-31 163 views
1

考慮你有一個abstract base class一個是從其他類X.面向對象的設計謎語

類重寫方法foo1繼承。

有幾個其他類A1,A2,A3是concrete類。所有具體類繼承方法foo1

方法foo1幾乎就像應該適用於所有具體類的通用算法。
這是「幾乎」,因爲算法中存在一個例外條件,某些類只能說A1,A3需要在foo的開始處放一些其他方法foo2。對於A2我們不需要啓動foo2

問題是如果我如果我在類A中實現foo2所有它的孩子也會繼承這個函數,這是不是很好的設計?

我想到將foo2排除在一個接口之外,這個接口將由具體的類實現 - >但這並不好,因爲foo1這叫foo2在基類上!

任何想法如何以適當的方式解決這個問題?

謝謝

+0

你可以做foo2的私人在A,而是增加其子類可以覆蓋一個受保護的虛擬財產,以及用於以一種確定的子類要調用foo2的在foo1的開頭。 –

+1

我想我理解並且看到了一個解決方案,但是我認爲如果你在你的問題ala'抽象類MyShape {....'中添加了一些簡單的代碼會更好。我不確定我是否遵循,但這會有所幫助 –

回答

2

我想在這種情況下使用的解決方案是使抽象類是需要特殊Foo2類,而不是從派生的另一層。

abstract class A : X 
{ 
    public virtual void Foo() 
    { 
     //Foo logic 
    } 
} 

abstract class B : A 
{ 
    protected virtual void Foo2() 
    { 
     //Foo2 
    } 

    override void Foo() 
    { 
     Foo2(); 
     base.Foo(); 
    } 
} 

public A1 : B 
{ 
} 

public A2 : A 
{ 
} 

public A3 : B 
{ 
} 
+0

這個實現的唯一缺點是它添加了另一個基類,其類別名可能不明顯。 – lukegravitt

+0

@lukegravitt在現實世界中,我會期待更多的描述性名稱,例如「X = Shape」,「A =多邊形」,「B =四邊形」,「A1 =平行四邊形」,「A2 =三角形」和「A3 =梯形」 –

0

在基類中創建一個屬性,當他們需要有一個名爲foo2的()子類可以設置:

public class BaseClass { 
    protected bool RunFoo2 { get; set; } 

    public BaseClass() { 
     // Not really needed, since booleans default to false 
     RunFoo2 = false; 
    } 

    public virtual void foo1() { 
     if (RunFoo2) 
      foo2(); 
     // Default code here 
    } 

    public virtual void foo2() { 
     // Whatever 
    } 
} 

public class A : BaseClass { 
    public A() : base() { 
     RunFoo2 = true; 
    } 
} 
+0

根據具體需要,您可以在此情況下使foo2()爲私有,非虛擬或兩者兼有。 – lukegravitt

2

你可以有某種內在Foo1初始化程序的你可以在子類中重寫。

public abstract class A { 
    internal virtual void Foo1Init() { 
     Console.WriteLine("Foo1Init"); 
    } 

    public void Foo1() { 
     Foo1Init(); 
     Console.WriteLine("Foo1"); 
    } 
} 

public class A1 : A { 
    internal override void Foo1Init() { 
     Console.WriteLine("A1 Foo1Init Override"); 
    } 
} 

public class A2 : A { 

} 

public class A3 : A { 
    internal override void Foo1Init() { 
     Console.WriteLine("A3 Foo1Init Override"); 
    } 
} 

class Program { 
    static void Main(string[] args) { 
     var a1 = new A1(); 
     a1.Foo1(); 

     var a2 = new A2(); 
     a2.Foo1(); 

     var a3 = new A3(); 
     a3.Foo1(); 

     Console.ReadKey(); 
    } 
} 

輸出:

 
A1 Foo1Init Override 
Foo1 
Foo1Init 
Foo1 
A3 Foo1Init Override 
Foo1