多态的用途是什么?

4
员工类
public class Employee {
protected String name;
protected String jobsheetnumber;

public Employee(String n,String j){
this.name = n;
this.jobsheetnumber = j;
}
public Employee(String name)
{
this.name = name;
}

public String getName() {
    return name;
}

public String getJobsheetnumber() {
    return jobsheetnumber;
}

public void setName(String name) {
    this.name = name;
}

public void setJobsheetnumber(String jobsheetnumber) {
    this.jobsheetnumber = jobsheetnumber;
}



}

机械师班级

public class Mechanic extends Employee{


public Mechanic(String name,String jobsheetnumber){
super(name,jobsheetnumber);
}
}

Supervisor类

public class Supervisor extends Employee{


public Supervisor(String name){
super(name);
}
}

公司类[代码片段]

public class Company {
private String companyname;
private String companyaddress;
private String postalcode;
private String city;
private String country;
private String telephonenumber;
private String faxnumber;
private String province;
private Employee supervisor;
private Employee mechanic;




public Company(String companyname,String companyaddress,String postalcode,String city,String country,String telephonenumber,String faxnumber,String province,String supervisorname,String jobsheetnumber,String mechanicname)
{
 this.companyname = companyname;
 this.companyaddress=companyaddress;
 this.postalcode = postalcode;
 this.city=city;
 this.country=country;
 this.telephonenumber=telephonenumber;
this.faxnumber=faxnumber;
this.province=province;
supervisor = new Supervisor(supervisorname);
mechanic = new Mechanic(mechanicname,jobsheetnumber);




}

员工类是机械师和主管类的超类。目前我在子类机械师和主管类中使用员工的属性,即姓名和工作单号。

代码运行良好...但如果我想在机械师和主管中添加扩展功能怎么办?因为引用是指向员工类型对象的,所以我无法访问这些变量。

这是多态的正确用法吗?我们必须每次创建主管/机械师对象的引用时都使用super()作为构造函数吗?我们不能在主管和机械师类中使用扩展功能吗?


1
你可以将引用强制转换,例如:Supervisor superRef = (Supervisor) company.supervisor; 然后访问superRef上的专门属性。 - AJ X.
1
这不是多态,这只是继承。多态应该是在员工中有一个抽象方法,并且对机械师和主管进行不同的实现。你不能通过公司实例访问主管和机械师属性,只是因为你将成员声明为员工。你应该分别将它们声明为主管和机械师。 - Martin Maat
3个回答

3

如果你想调用一个有参数的超类构造函数,那么是的,你必须显式地调用它。如果超类构造函数没有参数,则调用将为您插入。

多态的目的是让对象自己处理自己,而不必让程序的其余部分微观管理它们,因此外部程序通过具有接口或超类类型的引用来引用它们,而无需知道确切的具体类型。例如,所有员工都可能有一个工作方法,在那个工作对于主管和机械师来说采取不同的形式;工作方法将被特定的子类覆盖,并可能在子类上调用特定的方法。因此,公司可以遍历所有员工并在每个员工上调用工作,而对于不同的员工子类,工作的定义是不同的。

(实际上,使用子类描述角色太不灵活了,因为员工可能有多个角色,或这些角色随时间而变化。在这里,通常最好使用组合,将Role对象分配给Employee。)


1
更好的多态性应该是使用相同的接口(方法)来实现不同的实现。这样你就可以在运行时决定使用哪个实现。
为了解释我的观点,我将使用您的类举一个例子。
public class Employee{
    public void work(int hours){ doNothing();}      
}
public class Supervisor extends Employee{
    private Object pen; 
    private Object note;
    @Override
    public void work(int hours){
        observations = superviseWorkers();
        note.write(observations, pen);

    } 

}
public class Mechanic extends Employee{
    private Tool tool;
    private TaskBoard taskBoard;
    @Override
    public void work(int hours){ 
        task = taskBoard.getPendent()
        if(task.canSolveWithTool(tool))
        {
            solveTask(task, tool)
        }
    } 
}

使用示例:

employees = new List<Employee>();
employees.add(new Supervisor("foo"));
employees.add(new Mechanic("bar"));

foreach(employee in employees){
   //you don't need to know which kind of employee you are treating here because you are only calling a behavior that all employees have.
   employee.work(8);
}

如果你的代码中有很多地方需要确定正在处理哪个对象,那么你可能做错了。我在示例中使用了你的类来帮助你理解,但正如Nathan Hughes所建议的那样,在这种情况下最好使用组合而不是继承。

1
I will handle above scenario in two ways.
Solution 1: (接口作为角色)
  1. You can have "state" in Employee object and you can implement role as interface.
  2. Employee will have all common attributes & methods. You can override base class method like doWork() in respective Employee implementations.
  3. You can add specific behaviour of Mechanic, Supvervisor with use of interfaces.

    public interface ISupervise{
         public void doSupervise();
    }
    
    public class Supervisor extends Employee implements ISupervise{
        public void doSupervise(){
    
        }
    } 
    
    public interface IMechanic{
        public void doMechanicWork();
    }
    
    public class Mechanic extends Employee implements IMechanic{
        public void doMechanicWork(){
    
        }
    }
    

解决方案2: (装饰角色)

Employee实现装饰器模式,以扮演多个角色。 MechanicSupervisor将装饰Employee的行为。请参考此示例以更好地理解装饰器模式。

可在以下位置找到示例代码:

何时使用装饰器模式?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接