抽象类和多重继承

5
我们可以通过使用抽象类来实现与接口相同的功能,那么为什么Java不允许以下代码?
abstract class Animals
{
    public abstract void run();
}

abstract class Animals1
{
    public abstract void run1();
}

class Dog extends Animals,Animals1
{
  public void run() {System.out.println("Run method");}
  public void run1() {System.out.println("Run1 method");}
}

我知道多重继承可以通过仅使用接口来实现,但上述代码所做的与接口所做的相同。

可能是为什么Java或C#不允许多重继承?的重复问题。 - eol
我知道为什么Java不允许多重继承以及钻石问题,但是如果你看上面的例子,这只是接口实现的方式,所以对此有疑问。Peter Lawrey无论如何都回答了我的问题 :) - Zephyr
我同意,请看下面我的评论。 - Abhijit
5个回答

8

这是不允许的,因为你可以使用抽象类做更多的事情。如果你只能使用接口时使用抽象类,那么允许多重继承就没有意义了。

只有在你不能使用接口时才使用抽象类会更简单,这种情况下你将无法使用两个抽象父类。

注意:在Java 8中,你可以使用接口具有公共实例和静态方法及其实现,所以你不能做的事情更少了。

在Java 9中,你将能够在接口中使用private方法;)


1
能够在接口中拥有私有方法...真的!这是我第一次听说。因为我觉得现在(J8)的情况很荒谬:你在J8接口中的“默认”方法可以访问状态...但只能访问静态状态(接口可以包含静态字段)。难道不是时候让多重继承成为可能并“弃用”接口了吗?然后简单地让编译器要求具有歧义的子类解决这些歧义? - mike rodent
@mikerodent,我明白你的观点,但是Brian Goetz最近表示状态只会存在于类中,所以我认为短时间内不会有变化。状态并不是接口的一部分,而且字段始终都是final的(虽然它们可以是可变的)。 - Peter Lawrey

2
这是因为抽象类仍然属于类,而继承不同于实现接口。请参见抽象类和接口之间的区别。此外,请参见Java中实现接口和扩展类之间的区别
这两个问题涵盖了您需要了解的所有信息,以便理解为什么不能有多个抽象类的继承。
此外,让我举个例子说明为什么不应该允许这样做:假设您同时拥有AnimalsAnimals1实现相同的接口IAnimals
interface IAnimals
{
    public string eat();
}

abstract class Animals implements IAnimals
{
    public abstract void run();
    public string eat(){ return "Animals eating"; } 
}

abstract class Animals1 implements IAnimals
{
    public abstract void run1();
    public string eat(){ return "Animals1 eating"; } 
}

如果你现在像这样定义你的 Dog 类:

class Dog extends Animals,Animals1
{
  public void run() {System.out.println("Run method");}
  public void run1() {System.out.println("Run1 method");}
}

它还将有一个名为eat()的方法,它不是抽象的,因此可以直接使用。对于狗来说,这个方法的返回值是什么?会返回带有Animals的字符串,还是带有Animals1的字符串?
这被称为菱形问题,这是一些编程语言不允许多重继承的原因之一。

如果这些答案回答了相同的问题,你可以投票将其认定为重复。 - Peter Lawrey
1
@PeterLawrey,如果一个问题需要两个答案才能提供完整的信息,我应该投票关闭这个问题吗?当然,他可以通过阅读很多文章来找到他的问题的答案,但是就问题的表述而言,我不认为他的问题是我提出的问题中的“重复”。但是我必须承认,一瞬间我也在考虑同样的事情。 - meJustAndrew
当信息可用,但只有通过组合两个答案才能得到时,我倾向于不关闭问题,而是像您现在所做的那样,在新答案中包含相关信息。 - Peter Lawrey
1
@PeterLawrey 我知道这可以讨论,我也认为将答案保留原样是可以的,因为这对于遇到相同问题的任何人都更有帮助,比关闭问题更有意义。我认为这值得一试。 - meJustAndrew
我同意,一个综合的答案是一个值得添加的好东西。 - Peter Lawrey

0

0

如果我理解你的意思,我同意你的观点:这并不需要如此具体的命名约定。

interface pet
{

    public abstract void pet();
}

interface pet1
{
    public abstract void pet1();
}

class TestTt implements pet,pet1
{
    public void pet() 
    {
        System.out.println("this is method of pet interface");

    }

    public void pet1() {
        System.out.println("this is method of pet1 interface");

    }   
    public static void main(String a[])
    {
        pet obj=new TestTt();

        pet1 obj1=new TestTt(); 

        obj.pet();

        obj1.pet1();
    }       
}

现在,如果抽象类允许我创建对象。那么,我可以像接口一样为2个抽象类创建2个不同的引用。

如果是这样,我还需要接口吗?


-1
在抽象类中,我们不能同时继承多个抽象类。 但是,在接口中,我们可以同时实现多个接口。
因此,接口被用于在Java中实现多重继承。

3
不是的。实现接口与继承没有任何关系。在继承中,你应该继承父类的行为。当实现一个接口时,你只需要“保证”你的类具有与接口相同的方法。 - Federico klez Culloca

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