0
I came across a lot of code in our company codebase with the following structure



   class Base
    {
     public Base (var a, var b)
     {
      base_a = a;
      base_b = b;
     }

     var base_a;
     var base_b;
    }

    class Derived:Base
    {
     publc Derived (var a,b,c,d): base (a,d)
     {
       der_c = c;
       der_d = d;  
     }
     var der_c;
     var der_d;
     var der_e;
    }


    class  Ref
    {
     Base _ref;
     public Ref( var a,b,c,d)
     {
      _ref = new Derived (a,b,c,d)
     }

     public void method( )
     {
       _ref.der_e = 444; // won't compile
     }
    }

der_e を初期化する正しい方法は何ですか? 基底クラスの参照を持ち、 _ref にオブジェクト派生クラスを使用する利点は何ですか? 基本クラス参照を使用すると、複数の派生クラス オブジェクトを保持できるという事実だけでしょうか。その場合、派生クラスのすべてのメンバー変数は、構築自体中に初期化する必要があります (次のように: _ref = new Derived (a,b,c,d) )。メソッドで後で _ref.der_e を初期化したい場合はどうすればよいですか? 私はこれを行うことができることを知っています (var cast_ref = _ref as Derived; cast_ref.der_e = 444) が、この外観はベスト プラクティスではないようです。そのような構造を持つという考えは何ですか?また、構築された後に派生クラス オブジェクトのメンバーを初期化することの正しいのは何ですか?

4

2 に答える 2

0

これらは、1 つの投稿で多すぎる質問です。

der_e を初期化する正しい方法は何ですか?

初期化するには、クラスではなくder_eプロパティを知っているため、クラスder_eの参照が必要です。DerivedBase

基底クラスの参照を持ち、 _ref にオブジェクト派生クラスを使用する利点は何ですか?

はい、それはオブジェクト指向プログラミングの本質であるポリモーフィズムと呼ばれます。実際の実装を知らなくても、さまざまな具体的な実装を保持できます。

その場合、派生クラスのすべてのメンバー変数を構築中に初期化する必要があります (次のように: _ref = new Derived (a,b,c,d) )

そのようなルールはありません。シナリオによって異なります。オブジェクトの作成後に値を変更することを意図しておらず、オブジェクトの構築中に値が事前にわかっている場合は、構築中に初期化する必要があります。

繰り返しになりますが、値が既知である場合とそうでない場合があるなど、さまざまなシナリオがある場合は、異なる引数を取るオーバーロードされたコンストラクターが存在する可能性があります。

メソッドで後で _ref.der_e を初期化したい場合はどうすればよいですか?

それはまったく問題ありません。達成しようとしていることに依存します。質問は具体的なものではなく、達成しようとしていることについてコメントするのが難しい抽象的なものです。

私はこれを行うことができることを知っています (var cast_ref = _ref as Derived; cast_ref.der_e = 444) が、この外観はベスト プラクティスではないようです。

私はJavaのバックグラウンドを持っているので、C#に似たJavaコードを共有しています

//This class knows about Base and nothing about the Derived class
class UserOfBase{

   Base ref; 

   //Constructor of UserOfBase gets passed an instance of Base
   public UserOfBase(Base bInstance){
      this.ref = bInstance;
   }

   //Now this class should not cast it into Derived class as that would not be a polymorphic behavior. In that case you have got your design wrong.

   public void someMethod(){
        Derived derivedRef = (Derived)ref; //This should not happen here
   }

}

答えを説明すると非常に長くなる可能性があるため、これに役立つ参考文献をいくつか共有しています。

于 2013-08-02T06:10:55.950 に答える
0

派生クラスでコンストラクターを作成し、オブジェクトをマップするか、次のような拡張メソッドを作成できます。

  public static class Extensions 
  {            
        public static void FillPropertiesFromBaseClass<T1, T2>(this T2 drivedClass, T1 baseClass) where T2 : T1
        {
            //Get the list of properties available in base class
            System.Reflection.PropertyInfo[] properties = typeof(T1).GetProperties();

            properties.ToList().ForEach(property =>
            {
                //Check whether that property is present in derived class
                System.Reflection.PropertyInfo isPresent = drivedClass.GetType().GetProperty(property.Name);
                if (isPresent != null && property.CanWrite)
                {
                    //If present get the value and map it
                    object value = baseClass.GetType().GetProperty(property.Name).GetValue(baseClass, null);
                    drivedClass.GetType().GetProperty(property.Name).SetValue(drivedClass, value, null);
                }
            });
        }
  }

たとえば、次のようにクラス化する必要がある場合:

public class Fruit {
    public float Sugar { get; set; }
    public int Size { get; set; }
}
public class Apple : Fruit {
    public int NumberOfWorms { get; set; }
}

次のコードで派生クラスを初期化できます。

//constructor 
public Apple(Fruit fruit)
{            
   this.FillPropertiesFromBaseClass(fruit);
}
于 2020-07-28T15:02:10.630 に答える