2013-07-31 83 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