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

一个帖子里的问题太多了。

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

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

引用基类并为 _ref 使用对象派生类有什么好处?

是的,这就是所谓的多态性,它是面向对象编程的本质。它允许我们在不知道实际实现的情况下持有各种具体的实现。

如果是这种情况,是否应该在构造过程中初始化派生类的所有成员变量(例如: _ref = new Derived (a,b,c,d) )

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

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

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

那很好,这取决于您要达到的目标。这个问题不是一个具体的问题,而是一个抽象的问题,很难评论你想要达到的目标。

我知道我可以做到这一点(var cast_ref = _ref as 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
   }

}

我正在分享一些可以帮助您解决此问题的参考资料,因为我认为答案可能很长才能解释。

于 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 回答