12

サブクラスにコードがない場合、抽象クラスにサブクラスごとに静的変数の異なるコピーを持たせたいと思います。C#では

abstract class ClassA
{
    static string theValue;

    // just to demonstrate
    public string GetValue()
    {
        return theValue;
    }
    ...
}
class ClassB : ClassA { }
class ClassC : ClassA { }

および(たとえば):

(new ClassB()).GetValue(); // returns "Banana"
(new ClassC()).GetValue(); // returns "Coconut"

私の現在の解決策はこれです:

abstract class ClassA
{
    static Dictionary<Type, string> theValue;
    public string GetValue()
    {
        return theValue[this.GetType()];
    }
    ...
}

これは問題なく機能しますが、これを行うためのよりエレガントな方法や組み込みの方法があるのでしょうか。

これは、継承するクラスのタイプごとに静的変数の異なるコピーを持つことができますが、サブクラスを制御することはできません。

4

6 に答える 6

12

もっとエレガントな方法があります。ジェネリック基本クラスの静的が異なる型の派生クラスごとに異なるという事実を利用できます

public abstract class BaseClass<T> where T : class
{
    public static int x = 6;
    public int MyProperty { get => x; set => x = value; }
}

子クラスごとに、静的 int x は一意の T ごとに一意になります。2 つの子クラスを派生させて、子クラスの名前を基本クラスのジェネリック T として使用します。

public class ChildA: BaseClass<ChildA>
{
}

public class ChildB : BaseClass<ChildB>
{
}

これで、静的な MyProperty は ChildA と ChildB の両方で一意になります

var TA = new ChildA();
TA.MyProperty = 8;
var TB = new ChildB();
TB.MyProperty = 4;
于 2018-03-30T23:49:28.230 に答える
6

これは正常に機能しますが、これを行うためのよりエレガントな方法または組み込みの方法があるかどうか疑問に思っていますか?

ここで基本的なオブジェクト指向の原則に違反しているため、これを行うための組み込みの方法は実際にはありません。基本クラスには、従来のオブジェクト指向理論のサブクラスに関する知識がないようにする必要があります。

そうは言っても、これを行う必要がある場合、サブクラスに他の情報を直接追加できない限り、実装はおそらく得られるものとほぼ同じです。これを制御する必要があり、サブクラスを変更できない場合は、おそらくこれが最善の方法です。

于 2009-12-03T21:46:11.310 に答える
2

これはあなたが求めているものとは少し異なりますが、おそらく同じことを達成します。

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((new B()).theValue);
            Console.WriteLine((new C()).theValue);
            Console.ReadKey();
        }
    }

    public abstract class A
    {
        public readonly string theValue;

        protected A(string s)
        {
            theValue = s;
        }
    }

    public class B : A
    {
        public B(): base("Banana")
        {
        }
    }

    public class C : A
    {
        public C(): base("Coconut")
        {
        }
    }
于 2009-12-03T21:59:36.413 に答える
0

これはどうですか?



    class Base {
    protected static SomeObjectType myVariable;

    protected void doSomething()
    {
    Console.WriteLine( myVariable.SomeProperty );
    }
    }

    class AAA : Base
    {
    static AAA()
    {
    myVariable = new SomeObjectType();
    myVariable.SomeProperty = "A";
    }
    }

    class BBB : Base
    {
    static BBB()
    {
    myVariable = new SomeObjectType();
    myVariable.SomeProperty = "B";
    }
    }

わたしにはできる。インターフェースを使えばさらに良くなるでしょう。

于 2012-12-12T00:02:51.773 に答える
0

ユースケースに応じて、あなたのものよりも優れている場合とそうでない場合がある代替ソリューションがあります。

abstract class ClassA
{
    private static class InternalClass<T> {
        public static string Value;
    }
    public string GetValue()
    {
        return (string)typeof(InternalClass<>)
              .MakeGenericType(GetType())
              .GetField("Value", BindingFlags.Public | BindingFlags.Static)
              .GetValue(null);
    }
}

このアプローチは で使用されEqualityComparer<T>.Defaultます。もちろん、この問題には使用されません。抽象化を検討しGetValue、各派生クラスでオーバーライドする必要があります。

于 2009-12-03T21:48:06.853 に答える
-1

簡単な解決策: 「new」という単語を使用するだけです。

public abstract class AbstractClass
{
    public static int Variable;
}

public class RealizationA : AbstractClass
{
    public new static int Variable;
}

public class RealizationB : AbstractClass
{
    public new static int Variable;
}

そして結果:

AbstractClass.Variable = 1;
RealizationA.Variable = 2;
RealizationB.Variable = 3;
Console.WriteLine(AbstractClass.Variable); //1
Console.WriteLine(RealizationA.Variable); //2
Console.WriteLine(RealizationB.Variable); //3

またはプロパティを使用できます:

//in abstract class
public static int Variable {get; set;}
//in child class
public static new int Variable {get; set;}

または関数 (ただし、変数と関数の両方に「new」を追加することを忘れないでください):

//in abstract class
protected static int Variable;
public static int GetVariable() { return Variable; }
public static void SetVariable(int v) { Variable = v; }
//in child class
protected new static int Variable;
public static new int GetVariable() { return Variable; }
public static new void SetVariable(int v) { Variable = v; }

または、取得および設定する関数でプライベート変数 (「new」を使用する必要はありません) を使用できます。

//in abstract class
private static int Variable;
//get and set methods
//in child class
private static int Variable;
//get and set methods
于 2021-03-19T22:04:50.787 に答える