如何最好地应用DRY哲学并在每个类和子类的单个构造函数中设置标题?

时间:2016-06-16 03:48:48

标签: c# inheritance constructor

以下是一些示例代码(MWE):

public abstract class Employee
{
    protected string title = "Employee";  // underlying field

    public string Title { get { return title; } }  // read-only property
    public string Name { get; set; }  // another property

    public Employee() {}  // default ctor

    public Employee(string name) { Name = name; }  // ctor

    // how to use this in all subclasses without having to call in every ctor?
    protected Employee(string title) { this.title = title; }  // note this is protected ctor to prevent changes by users

    public virtual void Display()
    {
        Console.WriteLine("Title: {0}", Title);
    }
}


public class Associate : Employee
{
    // Properties
    public int NumberOfEngagements { get; set; }

    public Associate() : base("Associate")  // sets title as desired
    {
        NumberOfEngagements = 0;
    }

    public Associate(string name, int num_engagements)
        :base(name)
    {
        NumberOfEngagements = num_engagements;
    }
}


public class Director : Employee
{
    public int NumberOfProjectsManaged { get; set; }  // additional property

    public Director() : base("Director") { NumberOfProjectsManaged = 0; } // constructor

    public Director(string name, int num_projects)
        :base(name)
    {
        NumberOfProjectsManaged = num_projects;
    }

    public override void Display()
    {
        base.Display();
        Console.WriteLine("Number of Projects Managed: {0}", NumberOfProjectsManaged);
    }
}


public class Partner : Director
{
    // there are more than two in the actual code, but this is a MWE
    public enum SpecificTitle
    {
      Principal,
      Partner
    };

    public Partner() : base() 
    {
        this._setTitle(SpecificTitle.Partner);  // defaults to Partner
    }

    public Partner(SpecificTitle jobTitle) 
    {
        this._setTitle(jobTitle);  // overloaded ctor allows user to specify
    }

    private void _setTitle(SpecificTitle jobTitle)
    {
        switch (jobTitle)
        {
            case SpecificTitle.Principal:
                this.title = "Principal";
                break;
            case SpecificTitle.Partner:
            default:
                this.title = "Partner";
                break;
        }
    }
}

如何将标题设置为类名(在Partner中除外),而不必在每个构造函数中都这样做?

1 个答案:

答案 0 :(得分:1)

原始代码Title具有以下有趣属性:

  • 它是只读的(没有设定者)
  • 在构造函数中分配一次
  • 在大多数情况下,属性的值等于类名称

考虑到这一点,Title的值可以通过返回当前类类型名称来动态计算。它被声明为virtual,以便Partner类可以通过覆盖属性 getter 来改变默认行为

public abstract class Employee
{
    public virtual string Title 
    { 
        get { return GetType().Name; }
     }
}

public class Partner : Director {
{

      public Partner()  
      {
         this._jobTitle = SpecificTitle.Partner;  // defaults to Partner
      } 

       public Partner(SpecificTitle jobTitle) 
       {
          this._jobTitle = jobTitle;  // overloaded ctor allows user to specify
       }


     public override string Title { get {return GetJobTitle();}  


      public enum SpecificTitle
      {
          Principal,
          Partner
      };

       private SpecificTitle _jobTitle;


      private string GetJobTitle()
      {
          switch (_jobTitle)
           {
             case SpecificTitle.Principal:
               return "Principal";

             case SpecificTitle.Partner:
             default:
               return  "Partner";
            }
        }

    }


}

其余的类声明:

public class Associate : Employee
{
   // Properties
   public int NumberOfEngagements { get; set; }

   public Associate() 
   {
      NumberOfEngagements = 0;
   }

    public Associate(int num_engagements)
    {
       this.NumberOfEngagements = num_engagements;
    }

}

public class Director : Employee
{  
   public int NumberOfProjectsManaged { get; set; }  // additional property

   public Director() : { NumberOfProjectsManaged = 0; } // constructor

   public Director(int num_projects)
   {
       NumberOfProjectsManaged = num_projects;
   }

   public override void Display()
   {
       base.Display();
       Console.WriteLine("Number of Projects Managed: {0}", NumberOfProjectsManaged);
   }
}