Java中继承的概念

zaqlnxep  于 4个月前  发布在  Java
关注(0)|答案(2)|浏览(73)

你好,我是Java新手....从Objective C(iPhone背景)移动
我们所知道的是,这里我们不能使用多重继承。
另一种方式是接口......
我的问题是......通过接口继承有意义吗......因为我们必须在类中定义函数的代码.......这里唯一有帮助的部分是变量......它就像目标C中的单个.h类......
我说的只是那个接口的函数.
请告诉我为什么没有多重继承(简单的原因)。
我知道这可能是一个不好的问题,但...
我在黑暗中,请帮帮我……

0g0grzrc

0g0grzrc1#

我喜欢斯蒂芬施密特的这个回答。他清楚地解释了这一点:http://codemonkeyism.com/java-interview-questions-mutliple-inheritance/(链接失效)。

Java支持多重继承吗?

好吧,很明显,Java没有经典意义上的多重继承。所以正确的答案应该是“no”,或者“no,but”或者“yes,but”。从那里可以探索几种方法。我主要是从问Java语言设计者是否太愚蠢而不能实现多重继承开始的?为什么C++的家伙实现了它?我们主要是在钻石反模式上降落然后:
在具有多重继承和知识组织的面向对象编程语言中,菱形问题是当两个类B和C继承自A,而类D继承自B和C时产生的二义性。
另一种探索方法是Java如何“模拟”多重继承?答案可能已经浮出水面,就是接口。然后我们通常讨论Java中的接口,如果,何时以及如何候选人在过去使用它们。接口有什么好处,他喜欢它们吗?我可以探索他在建模方面有多好,有时让他画一个有接口的图。我们继续用Java解决接口问题,当两个接口有相同的静态字段,而一个类实现了这两个字段时,会发生什么--Java中的某种“多重继承”:

public interface I1 {
  String NAME = "codemonkeyism";
}

public interface I2 {
  String NAME = "stephan";
}

public class C implements I1, I2 {
  public static void main(String[] args) {
     System.out.println(NAME);
  }
}

字符串
为了保持真实性,语言设计师决定这在Java中不起作用:

C.java:3: reference to NAME is ambiguous, both variable NAME
             in I1 and variable NAME in I2 match
     System.out.println(NAME);
                        ^
1 error


还有更多的方法可以和候选人一起探索,例如接口方法的修饰符是什么。mixin或trait是比接口更好的钻石问题解决方案吗?或者它们和多重继承一样糟糕?因为我不再喜欢继承,并且认为大多数使用都是代码气味,所以也可以和候选人讨论继承的缺点-例如紧耦合。为什么?
为什么我会问这个问题,我从中学到了什么?继承是OO中一个非常基本的概念,每个Java开发人员都应该理解。反思他的工作并超越语法也是一个重要的特征,因此多重继承问题。我更喜欢产生许多探索机会的问题。继承问题是其中之一:多重继承,语言设计,代码气味,解决方案,接口,基于角色的开发。

2jcobegt

2jcobegt2#

我想补充一点。“
正如您从Tilsan The Fighter的深入解释中所理解的,Java不支持多重继承。
或者,你应该使用委托设计模式之一。我知道有时候代码看起来比使用多重继承的代码更冗长,但这是我们必须付出的代价。
你问了一个问题,为什么你需要创建一个实现多个接口的类?我想问你一个问题,为什么你需要接口?我认为答案是,这允许你把接口(合约)从具体实现中分离出来,使模块独立,简化重构,并使程序更灵活:只有当具体实现被接口隐藏时,你才能切换实现。
如果您的类可以在不同的上下文中用作A和B(其中A和B是接口),则该类应实现2个接口。
示例:假设您有一个只声明一个方法的业务接口Foo

int foo(String str);

字符串
现在创建两个实现Foo的类A和B:

public class A implements Foo {
    public int foo(String s) {
        return s.length();
    }
}

public class B implements Foo {
    public int foo(String s) {
        return s.hashCode();
    }
}


现在,您要创建Foo的集合:

Collection<Foo> collection = new ArrayList<Foo>();
collection.add(new A());
collection.add(new B());


使用这个集合的程式码并不知道任何关于具体实作的信息,但它并不会打扰它叫用foo()。
现在您希望对这个集合进行排序。方法之一是实现另一个接口Comparable:

public class A implements Foo, Comparable<Foo> {
    public int foo(String s) {
        return s.length();
    }
    public int compareTo(Foo o) {
        return getClass().getName().compareTo(o.getClass().getName());
    }
}


完成后,您可以说:

Collections.sort(collection);


集合将根据compareTo()中定义的规则进行排序。
现在,您可能希望序列化A和B的示例。为此,您必须实现另一个接口Serializable。幸运的是,Serializable是一个特殊的接口,它不声明任何方法。JVM知道序列化和去序列化作为Serializable示例的对象。

public class A implements Foo, Comparable<Foo>, Serializable {
    public int foo(String s) {
        return s.length();
    }
    public int compareTo(Foo o) {
        return getClass().getName().compareTo(o.getClass().getName());
    }
}


B类看起来是一样的。
现在我们可以说:

DataOutputStream os = new DataOutputStream(new FileOutputStream("/tmp/foo.dat"));
os.writeObject(new A());
os.writeObject(new B());
os.flush();
os.close();


并将对象存储在文件/tmp/foo.dat中。我们可以稍后读取这些对象。
我试图说明为什么我们需要实现几个接口的类:每个接口都给了类它的行为。Comparable允许对这样的示例的集合进行排序。Serializable允许序列化等。

相关问题