4

次のような基本クラスがあります。

class FooBase
{
    public bool Do(int p) { /* Return stuff. */ }
}

そして、このような子クラス:

class Foo<T> : FooBase
{
    private Dictionary<T, int> Dictionary;

    public bool Do(T p)
    {
        int param;
        if (!Dictionary.TryGetValue(p, out param))
            return false;
        return base.Do(param);
    }
}

ユーザーがFoo<string>「fooString」というオブジェクトを作成すると、両方を呼び出すことができますfooString.Do(5)が、「fooInt」fooString.Do("test")というオブジェクトを作成するFoo<int>と、派生クラスの Do メソッドしか呼び出すことができません。私はそれが何であれ、2番目を好みTます。

これら両方のクラスの Do メソッドは、基本的に同じことを行います。派生クラスのものは、指定されたパラメーターを使用して から整数を取得し、Dictionary<T, int>それを使用して基本クラスの Do メソッドを呼び出します。

FooBaseそのため、 inの Do メソッドを非表示にしたいと考えていFoo<T>ます。どうすればこれまたは同様のことを達成できますか? これを克服するための設計上のアドバイスもいいでしょう。

4

2 に答える 2

6

しかし、"fooInt" というオブジェクトを作成するFoo<int>と、派生クラスの Do メソッドしか呼び出すことができません。

いいえ、そうではありません。宣言された変数の型が の場合FooBaseでも、FooBaseメソッドが呼び出されます。へのアクセスを実際に妨げているのではなく、FooBase.Do単に隠しているだけです。

FooBase foo = new Foo<int>();
foo.Do(5); // This will still call FooBase.Do

次のことを示す完全なサンプル コード:

using System;

class FooBase
{
    public bool Do(int p) { return false; }
}

class Foo<T> : FooBase
{
    public bool Do(T p) { return true; }
}

class Test
{
    static void Main()
    {
        FooBase foo1 = new Foo<int>();
        Console.WriteLine(foo1.Do(10)); // False

        Foo<int> foo2 = new Foo<int>();
        Console.WriteLine(foo2.Do(10)); // True
    }
}

というわけで、FooBase の Do メソッドを Foo に隠したい。

Liskov の Substitutability Principleについて考える必要があります。

Foo<T>から派生してはならないFooBase(継承の代わりに構成を使用する) FooBase.Do表示されてはならない (たとえば、保護する)。

于 2012-08-01T11:47:39.447 に答える
0

メソッドを使用して抽象化された基本クラスを構築し、protected Do現在のクラスを次のように書き換えてFooBase継承することができFoo<T>ます。

public abstract class FooBaseAbstract
{
    protected bool Do(int p)
    {
        return true;
    }
}

// You can use this one just as your current FooBase class
public class FooBase : Foo<int>
{
}

public class Foo<T> : FooBaseAbstract
{
    public bool Do(T p)
    {
        if (true /* some test here */)
        {
            return base.Do(4);
        }

        return false;
    }
}

(もちろん、クラス名を変更します)

于 2012-08-01T11:47:33.417 に答える