「菱形继承Java」菱形继承时,继承的时候要加关键字防止内存浪费

博主:adminadmin 2023-01-10 07:30:06 1292

本篇文章给大家谈谈菱形继承Java,以及菱形继承时,继承的时候要加关键字防止内存浪费对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

为什么Java类只能继承一个父类

多重继承是一件很复杂、很容易产生问题的功能。它跟Goto语句一样,利弊交织。以下分两部分叙述,第一部分是Python多重继承遇到的麻烦,第二部分是Java和Ruby如何折中多重继承需求。============================================第一部分:Python是支持多重继承的,但为了解决多重继承的方法查找顺序问题(被称为MRO),有一场苦难史:1. 传统模式直接使用深度优先算法(并且,从左向右),每个类选择其第一次出现的位置。比如class A:

def save(self): pass

class B(A): pass

class C:

def save(self): pass

class D(B, C): pass

作为D类的一个实例,它的成员寻找顺序是:D、B、A、C。但当碰到如下这样一个“菱形继承”就麻烦了:class A:

def save(self): pass

class B(A): pass

class C(A):

def save(self): pass

class D(B, C): pass

作为D类的一个实例,寻找顺序也是D、B、A、C,但调用其save方法时,到底是调用A中的呢?还是C中的呢?直观上看,应该是C。这里有产生矛盾了。2. Python2.2的new-style class模式Python2.2中引进了new-style class,说白了就像java一样,所有类都继承自最根本的object类。这就让“菱形继承”变成十分普遍,于是只能改变MRO策略。仍然使用深度优先搜索、从左向右,但是每个类选择其最后一次出现的位置。这样一来,对上面的“菱形继承”就处理比较完美了,形成的顺序是:D、B、C、A,越是公用基础类,越放在后面。但是,碰到交叉继承,就又懵了。img src="" data-rawwidth="113" data-rawheight="179" class="content_image" width="113"这里,X和Y都继承自O,A继承(X,Y)(注意,有先后顺序),B继承(Y,X),再有个最下面的类继承(A,B)。这里,X和Y都继承自O,A继承(X,Y)(注意,有先后顺序),B继承(Y,X),再有个最下面的类继承(A,B)。按照上述算法出来的结果是:?、A、B、Y、X、O。这就有些奇怪了,明明A在B前,A继承的X在Y前,可为啥X的优先级比Y要低呢?3. C3算法1996年,一帮牛人写了一篇文章A monotonic superclass linearization for Dylan,提供了一个基于层级计算的线性MRO算法,被称为C3,整体上比较合理了。(算法不详说了)在2012年被加入了Dylan语言,2007年加入了Python2.3,此外还有Perl 6、Parrot等语言之中。这样虽说基本解决了计算问题,但多重继承本身就有很多让人疑惑的地方,比如:img src="" data-rawwidth="251" data-rawheight="171" class="content_image" width="251"参考文献:参考文献: Python 2.3 Method Resolution Order============================================第二部分:多重继承那么复杂,可单一继承又那么拘束,咋办呢?1. 接口继承Java就是那么做的,只允许单一继承类(方法的实现),但可以继承多个接口(方法的定义)。Java的接口继承功能,既实现了静态语言的多重继承性,又避免了多重继承的数据构造的冲突和类层次的复杂性。但是,我们并不能说接口是解决问题的完美方案。接口也有不能共享实现的缺点。本来只是为了跨越继承层次来共享代码,现在却需要另外生成一个独立对象,而且每次方法调用都要委派给这个对象,这实在是不太合理,而且执行的效率也不高。——《松本行弘的程序世界》2. Mix-in这是Ruby所推崇的,最初在Lisp中开始使用。规则如下:通常的继承都是单一继承。第二个以及两个以上的父类必须是Mix-in的抽象类(即不能单独生成实例,不能继承普通类)。这种规则下,既能够保持单一继承的结构,又能用Mix-in来共享方法的实现。

为什么Java不支持多重继承

简单

我想在这里分享一下James Gosling对于Java的定义。

Java: 一种简单的,面向对象的,分布式的,解释型的(译者注:Java既不是纯解释型也不是纯编译型的语言),健壮的,安全的,架构中立的,可移植的,高性能的,支持多线程的,动态语言。

看看定义的美妙之处吧。现代程序语言应该有这样的特性。我们看到,定义第一个特性是什么?是简单。

为了强化简单这个特点,这就是我们去除多重继承的原因。下面来看个例子,多重继承的菱形继承问题。

多重继承的钻石问题

有两个类B和C继承自A。假设B和C都继承了A的方法并且进行了覆盖,编写了自己的实现。假设D通过多重继承继承了B和C,那么D应该继承B和C的重载方法,那么它应该继承哪个的呢?是B的还是C的呢?

C++中经常会掉入这个陷阱,虽然它也提出了替代的方法来解决这个问题。我们在Java中就不会出现这个问题。就算两个接口拥有同样的方法,实现的类只会有一个方法,这个方法由实现的类编写。动态的加载类会让多重继承的实现变得困难。

很少使用

我们使用Java已经很长时间了,我们有多少次因为缺少多重继承而面临困难呢?我个人的经验是一次都没有。因为多重继承很少有机会被用到,所以更安全的做法是去掉它而保持简单性。

就算是碰到需要多重继承的情景,我们也可以找到替代方法。

Java怎样实现菱形继承

首先要有个表示People行为的接口:

public interface PeopleBehavior {

void sayName();

}

则有People类实现如下:

public class People implements PeopleBehavior {

private final String mName;

public People(final String name) {

mName = name;

}

@Override

public void sayName() {

System.out.println("People:" + "sayName:" + mName);

}

}

为了模拟C++的虚继承两边指向同一个虚基类对象,参考Decorator pattern的设计,关键在于要有一个People类的wrapper:

public class PeopleWrapper implements PeopleBehavior {

private final People mPeople;

public PeopleWrapper(final People people) {

mPeople = people;

}

@Override

public void sayName() {

mPeople.sayName();

}

}

表示Programmer行为的接口:

public interface ProgramBehavior {

void setLanguage(final String lanaguage);

void program();

}

则有Programmer类:

public class Programmer extends PeopleWrapper implements ProgramBehavior {

private String mLanguage;

public Programmer(final People people) {

super(people);

}

@Override

public void program() {

System.out.println("Programmer:" + "program:" + mLanguage);

}

@Override

public void setLanguage(final String lanaguage) {

mLanguage = lanaguage;

}

}

同理表示Manager行为的接口:

public interface ManagerBehavior {

void setStyle(final String style);

void manage();

}

Manager类:

public class Manager extends PeopleWrapper implements ManagerBehavior {

private String mStyle;

public Manager(final People people) {

super(people);

}

@Override

public void setStyle(final String style) {

mStyle = style;

}

@Override

public void manage() {

System.out.println("Manager:" + "manage:" + mStyle);

}

}

如此,不难得出ProgramManager类的设计:

public class ProgramManager extends PeopleWrapper implements ProgramBehavior,

ManagerBehavior {

private final ProgramBehavior mProgramAbility;

private final ManagerBehavior mManagerAbility;

public ProgramManager(final People people) {

super(people);

mProgramAbility = new Programmer(people);

mManagerAbility = new Manager(people);

}

@Override

public void setStyle(final String style) {

mManagerAbility.setStyle(style);

}

@Override

public void manage() {

mManagerAbility.manage();

}

@Override

public void setLanguage(final String lanaguage) {

mProgramAbility.setLanguage(lanaguage);

}

@Override

public void program() {

mProgramAbility.program();

}

}

菱形继承Java的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于菱形继承时,继承的时候要加关键字防止内存浪费、菱形继承Java的信息别忘了在本站进行查找喔。