7

在 C# 中,我有一个类层次结构,其中有几个靠近顶部的抽象基类和相当数量的派生类。这些具体类中的一些具有相同实现的一些公共属性和方法。我觉得这很浪费,因此一种解决方案可能是在另一个抽象基类中实现这种常见行为。

abstract class Control;

abstract class SquareControl: Control
{
    public int SquarishProperty;
    public void SquarishMethod();
};

class Window: SquareControl;
class Button: SquareControl;

但是,如果层次结构中的其他几个类共享一些其他行为,但也与另一个基类中的一个控件共享一些共同点怎么办?也许有很多共同点。用抽象基类实现对此进行建模将变得不切实际,不是吗?

abstract class FlashableControl: Control
{
    public int FlashyProperty;
    public void FlashMethod();
};

class StatusBar: FlashableControl;  // but it's also a bit square too, hmm...

那么如何在不使用基类的情况下跨类共享此类实现呢?

我想我想将接口的实现委托给另一个类,并让该类代表所需的类实现这些属性和方法,以便对用户而言,StatusBar 和 Window 似乎支持标准接口,但在涵盖它是实现它的其他东西。

我可以可视化实现这种行为的聚合类,但这是否合适,是否有任何陷阱?有哪些替代方案?

谢谢

4

3 回答 3

3

您可以使用这样的模式:

public interface ICommonServices
{
    string SomeProperty { get; set; }

    void SomeMethod(string param);
}

public static class CommonServiceMethods
{
    public static void DoSomething(this ICommonServices services, string param)
    {
        services.SomeMethod(services.SomeProperty + ": " + param + " something extra!");
    }
}

所有实现 ICommonServices 的类现在也可以通过扩展方法获得一些自由行为,这完全取决于所有 ICommonServices 实现者公开的那些特性。如果您需要访问基类功能,您可以将其放在它自己的接口中,并让 ICommonServices 也实现该接口。现在,您可以为接口创建“默认”扩展功能,而无需使用多个基类。


编辑

如果您希望其中一些方法是内部的,您可以像这样修改模式:

public class MyObject : IServices
{
    public string PublicProperty { get; private set; }

    string IServices.SomeProperty { get; set; }

    void IServices.SomeMethod(string param)
    {
        //Do something...
    }
}

public interface IPublicServices
{
    string PublicProperty { get; }
}

internal interface IServices : IPublicServices
{
    string SomeProperty { get; set; }

    void SomeMethod(string param);
}

internal static class ServiceMethods
{
    public static void DoSomething(this IServices services, string param)
    {
        services.SomeMethod(services.SomeProperty + ": " + param + " something extra!");
    }
}

基本上,我们公开了公共和内部接口。请注意,我们显式地实现了内部接口方法,因此这些方法不能供公共使用(因为公共客户端无法访问接口类型。)在这种情况下,辅助扩展方法是内部的,依赖于内部接口,尽管您也可以创建依赖于公共接口的公共辅助方法。

于 2010-06-18T22:00:01.567 回答
3

您可以使用 'has-a' 而不是 'is-a' 并委托给内部方形控件

    class Window : Control, ISquareControl
    {
        private SquareControl square;

        public void SquareOperation()
        {
            square.SquareOperation();
        }
    }

    class SquareControl : Control, ISquareControl
    {
        public void SquareOperation()
        {
            // ...
        }
    }
于 2010-06-18T21:49:51.380 回答
0

一种方法是使用接口和基类。

Flashable 将成为一个好的接口而不是一个类。

于 2010-06-18T21:54:13.747 回答