【问题标题】:Adding properties in derived class在派生类中添加属性
【发布时间】:2011-03-24 16:04:17
【问题描述】:

所以我正在尝试编写接口而不是实现。所以我有一个工厂,它返回一个派生自 Employee 的对象。所以这些对象可能是 Developer : Employee、Secretary : Employee 等。

所以我将 FirstName、LastName、Email 等所有共享属性放在基类 (Employee) 中。

而且我应该将特定于每种类型的所有属性都放在该类型中。因此,Developer 中会有一些属性,例如 Skills、ProgrammingLanguages 等,但是除非我使用 Developer 的具体类型,否则我将无法从 Employee 对象访问这些属性。

例如

Employee employee = new EmployeeFactory.CreateEmployee(EmployeeType.Developer);
employee.ProgrammingLanguages = "C#, Java, C++"; <-- compile error

解决这个问题的最佳方法是什么?反射...?

【问题讨论】:

  • 我认为在这种情况下你只需要在分配之前备份。
  • 在这种情况下,针对基类进行编码是没有意义的,因为您正在显式访问派生类中的属性
  • 如果您决定采用反射方式,您可能希望在 .NET 4 中使用 dynamic 关键字。这将使代码看起来更清晰。

标签: c# design-patterns


【解决方案1】:

如果您要明确说明使用哪种类型的员工,为什么还要麻烦工厂?

相反,你可以写:

Developer dev = new Developer();
dev.ProgrammingLanguages = "C#, Java, C++"; // compiles fine

稍后,您仍然可以将“开发人员”添加到员工列表中,即:

IList<Employee> theEmployees = GetEmployees();
theEmployees.Add(dev); // This is fine, since Developer is an Employee...

【讨论】:

  • 我明白你的意思,但我确实喜欢工厂,因为这样我可以将一些初始化(如 db 连接字符串)传递给每个派生类,并且用于获取初始化参数的所有逻辑都将集中在一个位置。虽然我想我可以将它移到基类中......但不确定两者的好处/坏处是什么。
  • @Joe:是的——它可以很容易地在基类中,并且只是传递给构造函数。除非您要“隐藏”真正的课程,否则几乎没有优势。
【解决方案2】:

为什么不使用泛型并拥有类似的东西

T EmployeeFactory.CreateEmployee<T>() 
{
     return new T();
}

然后这样称呼它

var dev = EmployeeFactory.CreateEmployee<Developer>();

这样你最终会得到一个有类型的 Developer。

【讨论】:

  • 这将要求在编译时知道Employee 的类型,这对于当前代码来说不是必需的。
  • 如果类型是可变的,则此代码将不起作用,但是当前代码或多或少地说明了类型是硬编码的(作为枚举)。
  • 我喜欢这个。但是,如何将参数发送给构造函数?公共静态 T EmployeeFactory() 其中 T : Employee { string someParam = "";返回新的 T(someParam); }
  • return (T)Activator.CreateInstance(typeof(T), newEmployeesRepository(connectionString));
【解决方案3】:

在您的代码中,显然当您尝试执行employee.ProgrammingLanguages 时,您知道employee 的类型为Developer。所以你可以直接转换:

Developer dev = new (Developer)EmployeeFactory.CreateEmployee(EmployeeType.Developer);
dev.ProgrammingLanguages = "C#, Java, C++";

或许更多:

Developer dev = new Developer(); // If you don't really need the factory.
dev.ProgrammingLanguages = "C#, Java, C++";

在您不知道是否可以这样做的情况下,您可以使用isas 进行测试。

将事情保持在他们可以处理的水平。显然,谈论可能不会编程的人的编程语言是没有意义的,因此可以在层次结构的Developer 级别工作。处理假期和工资的代码应该对所有员工都相同,或者至少通过一个可以覆盖的通用接口工作,因此它可以在层次结构的Employee 级别工作。

【讨论】:

    【解决方案4】:

    在我看来,至少在这种特定情况下,您不应该使用基本类型。

    您正在使用特定于 Developer 而不是通用 Employee 的东西,因此您失去了使用基本类型的好处。在这种情况下,只需创建一个新的开发者:

    Developer developer = new Developer();
    developer.ProgrammingLanguages = "C#, Java, C++";
    

    话虽如此,您总是可以尝试转换回更具体的类型:

    Employee employee = new EmployeeFactory.CreateEmployee(EmployeeType.Developer);
    
    Developer developer = employee as Developer;
    if(developer != null) developer.ProgrammingLanguages = "C#, Java, C++";
    

    【讨论】:

      【解决方案5】:

      在这种情况下,我建议使用最简单的解决方案。为每个员工类型创建一个方法,如下所示:

      public Developer CreateDeveloper();
      public Secretary CreateSecretary();
      

      为什么会有这种“丑陋”的解决方案?因为无论哪种方式,您都需要知道客户端代码中的类型。那么为什么要让泛型/反射复杂化呢?简单是神圣的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多