简体   繁体   中英

Adding properties in derived class

So I am trying to code to an interface rather than an implementation. So I have a factory that returns an object that derives from Employee. So these objects may be something like Developer : Employee, Secretary : Employee, etc.

So I put all of the shared properties like FirstName, LastName, Email, etc. in the base class (Employee).

And I should put all of the properties specific to each type in just that type. So Developer would have some properties in it like Skills, ProgrammingLanguages, etc. but then I will not be able to access these properties from the Employee object unless I use the concrete type of Developer.

eg

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

What's the best way to go about this? Reflection...?

Why bother with a factory if you're going to be explicitly saying what type of employee to use?

Instead, you can just write:

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

Later, you can still add the "developer" to a list of employees, ie:

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

Why not use generics and have something like

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

And call it like

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

That way you would end up with a typed Developer.

In your code, clearly when you try to do employee.ProgrammingLanguages you know that employee is of type Developer . So you can just cast to that:

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

Or more perhaps:

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

In contexts where you don't know if this can be done or not, you can test with is or as .

Keep things at the level they make sense to deal with them at. Clearly it doesn't make sense to talk about the programming languages of someone who might not program, so its fine to work at the Developer level of the hierarchy. Code for dealing with holidays and salary should either be the same for all employees, or at least work through a common interface with the possibility of overrides, and so it would work at the Employee level of the hierarchy.

It seems to me like, at least in this specific case, you shouldn't be using the base type.

You're working with something specific to a Developer rather than a generic Employee so you lose the benefit of working with the base type. In this case, just create a new developer:

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

That being said, you could always try a cast back to the more specific type:

Employee employee = new EmployeeFactory.CreateEmployee(EmployeeType.Developer);

Developer developer = employee as Developer;
if(developer != null) developer.ProgrammingLanguages = "C#, Java, C++";

In this case I would suggest using the simpliest solution. Create one method per one employee type, like this:

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

Why this "ugly" solution? Because you need to know the type in the client code either way. So why to complicate with generics/reflection? Simpicity is divine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM