使用基类引用对象初始化派生类成员变量

时间:2013-08-02 05:38:13

标签: c#-4.0 inheritance constructor initialization member

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为Derived; cast_ref.der_e = 444)但这看起来似乎不是最好的做法。有这样一个结构的想法是什么,以及在构造派生类对象的成员之后初始化它的正确性是什么?

2 个答案:

答案 0 :(得分:0)

单个帖子中的问题太多了。

  

初始化der_e的正确方法是什么?

对于初始化der_e,您必须具有Derived类的引用,因为它知道der_e属性而不是Base类。

  

拥有基类和使用的引用有什么好处   _ref?

的对象派生类

是的,这叫做Polymorphism,这是面向对象编程的本质。它允许我们在不知道实际实现的情况下持有各种具体实现。

  

如果是这样的话,应该是派生类的所有成员变量   在施工期间进行初始化(如下所示:_ref = new   派生(a,b,c,d))

没有这样的规则。这取决于您的情况。如果在创建对象后不打算更改这些值,并且在构造对象期间预先知道这些值,那么它们应该在构造期间初始化。

再次,如果有各种情况,例如有时值已知,有时不知道,则可能存在重载构造函数,它们采用不同的参数。

  

如果我想稍后在方法中初始化_ref.der_e怎么办?

这完全没问题,这取决于你想要实现的目标。这个问题不是具体的问题,而是一个抽象问题,很难对你想要实现的目标发表评论。

  

我知道我可以这样做(var cast_ref = _ref为Derived; cast_ref.der_e =   444)但这看起来似乎不是最好的做法。

我正在分享一些类似于C#的Java代码,因为我来自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
   }

}

我正在分享一些可以帮助你的参考文献,因为我认为答案可能需要很长时间来解释。

答案 1 :(得分: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);
}