Java中类层次结构的多重继承设计
我知道Java不支持多重继承。但如果我必须为动物王国设计一个课程体系。如何表示由两种不同动物杂交而成的动物?例如,骡子(驴或马?),狮虎(狮子或老虎)。如何继承Lion和Tiger类来创建Liger类?Java中类层次结构的多重继承设计,java,oop,Java,Oop,我知道Java不支持多重继承。但如果我必须为动物王国设计一个课程体系。如何表示由两种不同动物杂交而成的动物?例如,骡子(驴或马?),狮虎(狮子或老虎)。如何继承Lion和Tiger类来创建Liger类? 有没有一种不用老虎和狮子作为接口的方法?如果它们不能成为接口呢?正如您所提到的,这是不可能的。此外,这也可能是一个糟糕设计的标志(因为即使可能,它也可能带来歧义)。因此,您可能必须尝试避免它,并重新考虑您的设计。如果您希望一个对象可以同时识别为两个对象,则它们始终需要是接口 您通常可以将行为委托
有没有一种不用老虎和狮子作为接口的方法?如果它们不能成为接口呢?正如您所提到的,这是不可能的。此外,这也可能是一个糟糕设计的标志(因为即使可能,它也可能带来歧义)。因此,您可能必须尝试避免它,并重新考虑您的设计。如果您希望一个对象可以同时识别为两个对象,则它们始终需要是接口 您通常可以将行为委托给复合类,但对于liger(它几乎是我最喜欢的子类),您需要确定哪种动物的行为具有优先权。狮虎可能是一个或另一个的直系后裔,也可能两者都不是
Java只允许多个“API继承”(接口),不支持实现。Java不支持多类继承。考虑“狮子”和“老虎”可能有共同的功能。Java不想解决“函数冲突”问题: 应该打印什么
Java不支持多类继承,因此这不起作用-类声明中的“extends Lion,Tiger”部分是非法的。Java支持接口的消歧机制,但这并没有扩展到类 最好的办法是将每个动物类转换为接口,然后将代码转换为这些接口的实现。Liger的实现方式如下:
interface Liger extends Lion, Tiger { }
class LigerImpl implements Liger{
private Lion mom;
private Tiger dad;
public LigerImpl(){
mom = new LionImpl();
dad = new TigerImpl();
}
public String call(){
if(math.random() > 0.5){
return mom.call();
} else {
return dad.call();
}
}
这种方法需要明确地委托给每个底层实现;绝对没有“免费”的事情发生。不过,Java不会让你离得更近。Java的设计几乎可以归结为“如果任何东西在任何方面都不明确、不安全、未定义,或者可能导致类型或解析冲突,请让程序员编写更多代码。”在这种情况下,继承不是正确的工具。你看,狮虎不是老虎,也不是狮子。它具有两者的特点,但两者都不是 假设你去动物园,笼子上写着“老虎”。你往里看,看到这只奇怪的巨猫,你肯定认不出它是老虎,但不是老虎。你也不认为它是狮子。这两个都不适合 因此,它应该组成一只
狮子
和一只老虎
,并将其行为委托给正确的一只,或者完全或部分“覆盖”它们的行为
更新:
现在,如果你真的想要某种多重继承,比如如果你想从一只杂交猫和一只猫科动物中衍生出一只猫科动物,该怎么办?看看有没有可能。要在Java中实现它,您需要为设计中要倍增“继承”的每个概念提供一个接口和一个类。看看这个想法。我不建议你这么做,但反思可能会奏效。当然,使用“instanceof”永远不会起作用
public class Lion {
public void roar() {
System.out.println("Lion is roaring");
}
public void eat(String what) {
System.out.println("Lion is eating " + what);
}
}
public class Tiger {
public void purr() {
System.out.println("Tiger is purring");
}
public void eat(String what) {
System.out.println("Tiger is eating " + what);
}
}
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Liger {
public static void main(String[] args) {
Liger liger = new Liger();
liger.purr();
liger.roar();
liger.eat("food");
//Result
//Tiger is purring
//Lion is roaring
//Tiger is eating food
//Lion is eating food
}
private ArrayList<Object> _extends = new ArrayList<Object>();
public Liger() {
_extends.add(new Tiger());
_extends.add(new Lion());
}
private void invoke(String methodName, Object... args) {
for ( Object obj : _extends ) {
Class cls = obj.getClass();
Method[] methods = cls.getMethods();
for ( Method m : methods ) {
if ( m.getName().equals(methodName) ) {
try {
m.invoke(obj, args);
}
catch ( Exception ex ) {
//handle me
}
continue;
}
}
}
}
public void purr() {
invoke("purr"); //Tiger only
}
public void roar() {
invoke("roar"); // Lion only
}
public void eat(String what) {
invoke("eat", what); //Both
}
}
公共类狮子{
公众虚空咆哮{
System.out.println(“狮子吼叫”);
}
公共空吃(串什么){
System.out.println(“狮子在吃”+什么);
}
}
公共级老虎{
公共空间purr(){
System.out.println(“老虎在呜呜叫”);
}
公共空吃(串什么){
System.out.println(“老虎在吃”+什么);
}
}
导入java.lang.reflect.Method;
导入java.util.ArrayList;
公共级狮虎{
公共静态void main(字符串[]args){
Liger Liger=新Liger();
liger.purr();
狮虎吼叫;
吃(“食物”);
//结果
//老虎在咕噜咕噜
//狮子在吼叫
//老虎正在吃食物
//狮子正在吃食物
}
private ArrayList_extends=new ArrayList();
公共Liger(){
_extends.add(newtiger());
_extends.add(newlion());
}
私有void调用(字符串方法名、对象…参数){
对于(对象对象对象:_扩展){
类cls=obj.getClass();
方法[]methods=cls.getMethods();
用于(方法m:方法){
if(m.getName().equals(methodName)){
试一试{
m、 调用(obj,args);
}
捕获(例外情况除外){
//对付我
}
继续;
}
}
}
}
公共空间purr(){
invoke(“purr”);//仅限老虎
}
公众虚空咆哮{
调用(“咆哮”);//仅限狮子
}
公共空吃(串什么){
调用(“吃”,什么);//两者
}
}
它是否会带来歧义取决于子类是什么。IMHO,对于Liger来说,它很可能会带来歧义。当然,但它总是取决于子类是什么,以及类的行为。我的观点是,说这是糟糕设计的标志是一种笼统的概括,我认为这是不可靠的。这只是一种丑陋、不可靠的授权方式。很好的解释!现在更清楚的是如何处理这种情况。我不太熟悉代表团和组成的概念,但一定会深入学习。谢谢你的帮助。
public class Lion {
public void roar() {
System.out.println("Lion is roaring");
}
public void eat(String what) {
System.out.println("Lion is eating " + what);
}
}
public class Tiger {
public void purr() {
System.out.println("Tiger is purring");
}
public void eat(String what) {
System.out.println("Tiger is eating " + what);
}
}
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Liger {
public static void main(String[] args) {
Liger liger = new Liger();
liger.purr();
liger.roar();
liger.eat("food");
//Result
//Tiger is purring
//Lion is roaring
//Tiger is eating food
//Lion is eating food
}
private ArrayList<Object> _extends = new ArrayList<Object>();
public Liger() {
_extends.add(new Tiger());
_extends.add(new Lion());
}
private void invoke(String methodName, Object... args) {
for ( Object obj : _extends ) {
Class cls = obj.getClass();
Method[] methods = cls.getMethods();
for ( Method m : methods ) {
if ( m.getName().equals(methodName) ) {
try {
m.invoke(obj, args);
}
catch ( Exception ex ) {
//handle me
}
continue;
}
}
}
}
public void purr() {
invoke("purr"); //Tiger only
}
public void roar() {
invoke("roar"); // Lion only
}
public void eat(String what) {
invoke("eat", what); //Both
}
}