7

C#では、クラス階層があり、最上位にいくつかの抽象基本クラスがあり、かなりの数の派生クラスがあります。これらの具象クラスのいくつかには、同じように実装されるいくつかの共通のプロパティとメソッドがあります。それは無駄だと思うので、1つの解決策は、この一般的な動作を別の抽象基本クラスに実装することかもしれません。

abstract class Control;

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

class Window: SquareControl;
class Button: SquareControl;

ただし、階層内の他のいくつかのクラスが他の動作を共有しているが、別の基本クラスのコントロールの1つと共通点がある場合はどうなるでしょうか。おそらく、共通点がたくさんあります。これを抽象基本クラスの実装でモデル化することは非現実的になりますね。

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

'is-a'の代わりに'has-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 に答える
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 に答える
0

1つの方法は、インターフェイスと基本クラスを使用することです。

Flashableは、クラスの代わりに優れたインターフェイスになります。

于 2010-06-18T21:54:13.747 に答える