Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中类层次结构的多重继承设计_Java_Oop - Fatal编程技术网

Java中类层次结构的多重继承设计

Java中类层次结构的多重继承设计,java,oop,Java,Oop,我知道Java不支持多重继承。但如果我必须为动物王国设计一个课程体系。如何表示由两种不同动物杂交而成的动物?例如,骡子(驴或马?),狮虎(狮子或老虎)。如何继承Lion和Tiger类来创建Liger类? 有没有一种不用老虎和狮子作为接口的方法?如果它们不能成为接口呢?正如您所提到的,这是不可能的。此外,这也可能是一个糟糕设计的标志(因为即使可能,它也可能带来歧义)。因此,您可能必须尝试避免它,并重新考虑您的设计。如果您希望一个对象可以同时识别为两个对象,则它们始终需要是接口 您通常可以将行为委托

我知道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
    }
}