为什么不能在Java 8中通过调用特定类的方法名来使用多重继承?

huangapple 未分类评论46阅读模式
英文:

Why can't we use multiple inheritance in Java 8 by calling the specific class's method name?

问题

Java 8中接口的默认方法可以在子类中使用InterfaceName.super.methodName的方式进行调用。为什么Java 8不允许我们使用类似的语法来调用特定类的方法呢?这样能够解决多继承所遇到的菱形继承问题吗?

class Employee {
    public static void displayName() {
        System.out.println("Employee!");
    }
}

class Engineer extends Employee {
    public static void displayName() {
        System.out.println("Engineer!");
    }
}

class Manager extends Employee {
    public static void displayName() {
        System.out.println("Manager!");
    }
}

public class Resource extends Engineer, Manager {

    public static void main(String args[]) {
        // 在这里插入类似的代码,类似于 InterfaceName.super.methodName 的方式调用上述任一方法,以处理多继承。
    }

}
英文:

Java 8's default methods in an interface can be called from the child class using InterfaceName.super.methodName . Why doesn't Java 8 allow us to use a similar syntax to call the specific class's method name? Can this resolve the Diamond Problem encountered for multiple inheritance?

class Employee {
	public static void displayName() {
		System.out.println("Employee!");
	}
}

class Engineer extends Employee {
	public static void displayName() {
		System.out.println("Engineer!");
	}
}

class Manager extends Employee {
	public static void displayName() {
		System.out.println("Manager!");
	}
}

public class Resource extends Engineer,Manager {

	public static void main(String args[]) {
		//Insert similar code here like InterfaceName.super.methodName to call any of the above methods to handle multiple inheritance.
	}

}

答案1

得分: 0

在Java 8中,你不能一次性地继承多个类。我的意思是,如果你写:

public class Resource extends Engineer, Manager { // 这会产生编译错误。
}

然而,你可以通过构建继承链的方式,在一个主类中继承多个类。

public class Master {
  public void method1(){};
}

public class Child1 extends Master{
  public void method2() {};
}

public class Child2 extends Child1 {
  // 你可以通过简单调用 method1() 和 method2() 来访问这里的方法
  method1();
  method2();
}

解决这个问题的一种方法是编写一个 "EmployeeInterface" 接口,并编写一个 "EmployeeClass" 类。要访问 "EmployeeClass" 中的方法,你必须在主方法中创建一个 "EmployeeClass" 对象。你需要编写一个构造函数来传递员工的名字。我在这里提供一个示例:

public interface EmployeeInterface {
  public void displayName();
  public void setName(String name);
}

上面是一个接口。接口包含你想在类中使用的方法,但是在这里你还没有定义它们的实现。你只编写了方法头部。可以将这看作是一个购物清单。在购物清单上写上面包这样的物品并不意味着你现在就有面包了,它只是将其标记为需要购买的物品。

接下来,你需要编写一个实现了 "EmployeeInterface" 的类。

public class EmployeeClass implements EmployeeInterface {
  private String employeeName;

  public EmployeeClass(String name) { // 这是一个构造函数
    this.employeeName = name;
  }

  @Override
  public void displayName() {
    System.out.println(employeeName);
  }

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

上面是实现了 "EmployeeInterface" 的类。它查看接口并表示你必须定义这些方法的实现。这就像看到购物清单上有面包,然后去商店买面包一样。

在这个类中还有一个构造函数。在Java中,构造函数是在类的实例化时执行的方法。这意味着你在构造函数中编写的代码将在创建类的对象时运行一次且仅运行一次。构造函数的名称必须与类名相同,且大小写敏感,必须是公共的。你可以添加任意数量的参数。

我们在类中的函数上使用 @Override,因为我们正在从 "EmployeeInterface" 中的空实现中进行重写(改变其具体实现)。根据你使用的IDE/编译器,可能在没有 @Override 标记的情况下也可以工作,但强烈建议使用这个标记。

在构造函数中,你看到我们使用了 this.employeeName = name;,"this" 关键字指的是类中的字段(变量)。在这种情况下,这并不是必要的,因为类中的变量名和传入的变量名是不同的。但是在变量名相同的情况下,你可以使用 "this.variableName" 来指定类变量。

最后,要使用这些类,你必须在一个单独的类中创建一个主方法来执行这些函数。创建主方法就像用从商店购买的面包做三明治一样。

public class Main {
  public static void main(String[] args)  {
    EmployeeInterface manager = new EmployeeClass("Bob");
    EmployeeInterface engineer = new EmployeeClass("Mary");
    
    System.out.println("The name of the manager is: ");
    manager.displayName();
    
    System.out.println("The name of the engineer is: ");
    engineer.displayName();
    
    manager.setName("Jack");
    System.out.println("The new manager's name is: ");
    manager.displayName();
  }
}

上面的方法执行了你在 "EmployeeClass" 中定义的方法,使用了 "EmployeeInterface"。首先,你创建了一个类的对象,类型是接口的名称。

EmployeeInterface manager = new EmployeeClass("Bob");

这是一个 "EmployeeClass" 的对象,我们称之为 manager。我们将其声明为 EmployeeInterface 类型,因为我们想要能够使用在 "EmployeeInterface" 中定义的方法。之后,我们写上 "= new EmployeeClass("Bob");",因为我们想要创建一个新的 "EmployeeClass" 实例,并将字符串 "Bob" 传递给我们的构造函数。

接下来,我们显示经理的名字。

System.out.println("The name of the manager is: ");
manager.displayName();

这将显示经理的名字。

我们还可以使用我们定义的 "setName()" 函数更改经理的名字。

manager.setName("Jack");

我们像这样调用函数,并传递字符串 "Jack",它将成为经理的新名字。

执行 Main 方法后,我们会得到这个输出。

总的来说,这个解决方案不使用方法继承来打印不同员工的名字,而是使用了 EmployeeInterface,以及 EmployeeClass 的定义,来存储和显示员工的名字。与为每个员工创建一个新类不同,你在主方法中创建一个包含新员工名字的新对象。

希望这回答了你的问题,如果需要更多的解释,请回复。

英文:

In Java 8, you can not extend (inherit) multiple classes all in one shot. What I mean by this is that if you write:

public class Resource extends Engineer, Manager { //This generates a compiler error.
}

However, you may inherit multiple classes into one, main class by making a chain of inheritance.

public class Master {
  public void method1(){};
}
public class Child1 extends Master{
  public void method2() {};
}
public class Child2 extends Child1 {
  //you can access method 1 and method 2 here by simply calling
method1();
method2();
}

A way you can go about addressing your issue is to write an "EmployeeInterface" and write an "EmployeeClass". To access the methods in "EmployeeClass", you must make an object of the "EmployeeClass" in your main method. You will need to write a constructor to pass the name of the employee in. I will provide an example here:

public interface EmployeeInterface {

public void displayName(); 

public void setName(String name);

}

The above is an Interface. An interface contains the methods that you want to use in a class, however, you do not yet define them here. You only write the method headers. Think of this as a shopping list. Writing an item such as bread on a shopping list does not mean you will now have bread, it just marks it as an item that needs to be purchased.

Next, you will need to write a class implementing the EmployeeInterface.

public class EmployeeClass implements EmployeeInterface{

private String employeeName;

public EmployeeClass(String name) { //This is a constructor
	this.employeeName = name;
}

@Override
/**
 * This function will display the name of the employee.
 */
public void displayName() {
	System.out.println(employeeName);
}

@Override
/**
 * This function with use the given string and change the employee's name.
 */
public void setName(String name) {
	this.employeeName = name;
 }//end of setName method
}//end of class

Above is the class that implements the EmployeeInterface. It looks at the Interface and says that you must define what these methods do. This is like looking at your shopping list and seeing bread, and going to the store and buying it.
There is also a constructor in this class. A constructor in java is a method that is executed upon the instantiation of an instance of a class. This means that whatever code you write in the constructor, it will be run once and only once when you make an object of the class. Constructors must be spelled the same as the class, is case sensitive, and must be public. You can add as many parameters as you'd like.
We use @Override over the functions in the class because we are overriding (Changing the body) from nothing to our definition from the EmployeeInterface. Depending on your IDE/Compiler, it may work without the @Override tag, but it is highly reccomended that you do this.
In the constructor, you see we use this.employeeName = name; the "this" keyword refers to the field (variable) within the class that we write it in. In this case, it is not necessary, because the name of the variable in the class and the name of the variable being passed in are different. But in the case that variable names are the same, you can use "this.variableName" to specify the class variable.

Finally, to use these classes, you must make a main method in a separate class to execute these functions. Making the main method is like making a sandwich out of the bread that you purchased at the store.

public class Main {

public static void main(String[] args)  {
	
	EmployeeInterface manager = new EmployeeClass("Bob");
	EmployeeInterface engineer = new EmployeeClass("Mary");
	
	System.out.println("The name of the manager is: ");
	manager.displayName();
	
	System.out.println("The name of the engineer is: ");
	engineer.displayName();
	
	manager.setName("Jack");
	System.out.println("The new manager's name is: ");
	manager.displayName();

  }//end of method Main
}//end of class Main

Above is the method that executes the methods that you defined in the EmployeeClass using the EmployeeInterface. First, you create an object of the class, of the type that is the name of the Interface.

EmployeeInterface manager = new EmployeeClass("Bob");

This is an object of the EmployeeClass, and we called it manager. We made it of type EmployeeInterface because we want to be able to use the methods we defined in the EmployeeInterface. We write "= new EmployeeClass("Bob");" afterward because we want to make a new Instance of the EmployeeClass, and pass the String "Bob" into our constructor.

Next, we display the name of the manager.

	System.out.println("The name of the manager is: ");
	manager.displayName();

This will display the name of the manager.

We can also change the name of the manager with our defined "setName()" function.

manager.setName("Jack");

We call the function like this and pass in the String "Jack" which will become the new name for the manager.

Upon execution of the Main method, we get this output:
Image of the output

All in all, this solution does not use inheritance of methods to print the names of different employees, but uses an EmployeeInterface, along with a definition of the Interface, EmployeeClass, to store and display the employee names. Rather than making a new class for every employee, you make a new object with the parameters containing the name of the new employee in the main method.

I hope this answered your question, and please do reply if you require any more clarifications.

Here I also include some articles about the Java concepts I talked about.

Here is a resource for Inheritance and Interfaces.

Interfaces on Oracle

Inheritance on Oracle

Constructors on Oracle

huangapple
  • 本文由 发表于 2020年5月4日 00:04:45
  • 转载请务必保留本文链接:https://java.coder-hub.com/61577584.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定