7

プロパティでさまざまな種類の値を取得できるクラスを作成したいと考えています。ポリモーフィズムを使用してこれを実行しようとしていますが、これを適切に行う方法をまだ学んでいないため、アドバイスを求めています。

基本クラスと、それを継承する 2 つのクラスがあります。

public abstract class BaseClass
{
    public string Name { get; set; }
    public Unit Unit { get; set; }
}

public class DerivedClassFloat : BaseClass
{
    public float Value { get; set; }

    public override string ToString()
    {
        return Value.ToString();
    }
}

public class DerivedClassString : BaseClass
{
    public string Value { get; set; }

    public override string ToString()
    {
        return Value;
    }
}

リストを作成し、さまざまな特殊なサブクラスを追加できます。私の問題は、リスト内の項目の値を変更する必要がある場合に発生します。

foreach (var item in ListOfBaseClasses)
{
   if(item is DerivedClassFloat)
     ((DerivedClassFloat) item).Value = float.NaN;
   if (item is DerivedClassString)
      ((DerivedClassString) item).Value = string.Empty;
}

私が読んだことによると、それはコードの匂いのようです。割り当てようとしている型に基づいて、派生クラスの値プロパティにアクセスするより良い方法はありますか?

値に基づいて適切なサブクラスを作成したい場合はどうでしょうか?

BaseClass newClass = null;
if (phenotype is DerivedClassFloat)
    newClass = new DerivedClassFloat(){Value = 12.2};
if (phenotype is DerivedClassString)
    newClass = new DerivedClassString(){Value = "Hello"};                      

仮想メソッドのオーバーライドについて読みましたが、値を追加または変更するのではなく、値を処理したい場合に機能します...何か足りないのでしょうか?


これをもっと具体的にする必要があります。申し訳ありませんが、この素晴らしいサイトに質問を投稿することに慣れていません。

属性のリストで構成されるプロパティが必要です。各属性には名前と値がありますが、値は異なる型にすることができます。例えば:

public class Organism
{
    public string Name { get; set; }
    public List<Attribute> Attributes { get; set; }
}

public class Attribute
{
    public string AttributeName { get; set; }
    public object AttributeValue { get; set; }
}

特定の生物に対して、異なる値の型を持ついくつかの属性を持つことができます。正しい型にキャストする必要がないように、オブジェクト型の使用を避けたかったのです。プロパティのポリモーフィズムは、このケースをエレガントに処理するためのソリューションであると考えていましたが、そもそもキャストとあまり変わらないように思われる If ..Then を使用していることに気付きました。

4

6 に答える 6

2

この特定のケースでは、ジェネリックを使用できます。

public abstract class BaseClass<T>
{
    public string Name { get; set; }
    public Unit Unit { get; set; }
    public T Value { get; set; }
}

public class DerivedClassFloat : BaseClass<float>
{
    public override string ToString()
    {
        return Value.ToString();
    }
}

public class DerivedClassString : BaseClass<string>
{
    public override string ToString()
    {
        return Value;
    }
}
于 2012-04-21T19:41:32.290 に答える
2

特定のケースでリセットしたい場合は、基本クラスでValue抽象ResetValueメソッドを定義できます。これは、派生クラスによって実装されます。

2番目のケースについては、Creational Design Patterns、具体的にはFactoryおよびPrototypeデザインパターンを確認する必要があります。

于 2012-04-21T19:37:04.150 に答える
1

ジェネリックスを使用して型を定義でき、実装サブクラスはValue型を型制約に設定します。

public abstract class BaseClass<T>
{
    public string Name { get; set; }
    public Unit Unit { get; set; }
    public T Value { get; set; }

    public override string ToString()
    {
        return Value.ToString();
    }
}

public class DerivedFloat : BaseClass<float> {}

public class DerivedString : BaseClass<string> {}
于 2012-04-21T19:41:18.320 に答える
1

ポリモーフィックな動作は、抽象化で機能します。何をしようとしているかに基づいて、コードの可変性を基本クラスに移動することで、コードの臭いを減らすことができます。

次のようなプロパティ書き込みメソッドの代わりになることをお勧めします。次のようなことができます。

public void setValue(string val, Type type);//move this to your base class

    Class MyValue{
private string strVal;
private int intVal;

//constructor
MyValue(string val, Type type){
     //check the type enum here and set the values accordingly
}
}

then when set values
foreach (var item in ListOfBaseClasses)
{
     item.setValue = MyValue("",Type.INT);
}
于 2012-04-21T19:48:03.907 に答える
0

このアプローチで何を達成しようとしているのかよくわかりません-Valueプロパティは同じタイプではなく、基本クラスにはValueプロパティもありません。これは、基本クラスから派生した他のタイプにそれがない可能性があることを示唆しています。まったく。

すべてのクラスにValueプロパティが必要な場合は、おそらく最も一般的なタイプである必要がありobjectます。基本クラスに配置できますが、派生クラスに値をキャストする必要があります。ただし、NullObject派生クラスごとにValueプロパティに割り当てることができる値の欠如を表すaを使用できます。

于 2012-04-21T19:38:38.173 に答える
0

抽象ファクトリ パターンを使用できます。次の例を検討してください。

// Base class

class Button
{
    protected Button()
    {
    }

    public string Name { get; set; }
}

// Factory interface

public interface ButtonFactory
{
    Button CreateButton();
}

// And the concrete classes

class WindowsButton : Button
{
    // ...
}

class WindowsButtonFactory : ButtonFactory
{
    public Button CreateButton()
    {
        return new WindowsButton();
    }
}

class MacButton : Button
{
    // ...
}

class MacButtonFactory : ButtonFactory
{
    public Button CreateButton()
    {
        return new MacButton();
    }
}

さらに、抽象ファクトリ パターン戦略パターンと組み合わせて、型によって変化するカスタム動作をカプセル化できます。

于 2012-04-21T19:58:45.547 に答える