java中的多态与继承_精选Java中的多态和继承

在优锐课架构学习中,了解了关于用多态方法调用将你的大脑包围在Java方法调用周围

根据传说中的Venkat Subramaniam,多态是面向对象编程中最重要的概念。 多态性(或对象根据其类型执行特殊操作的能力)使Java代码具有灵活性。 诸如 四个人帮 之类的设计模式(例如Command,Observer,Decorator,Strategy和许多其他模式)都使用某种形式的多态性。 精通此概念可极大地提高你思考解决编程难题的能力。

Juggy:

public abstract class JavaMascot {

public abstract void executeAction();}public class Duke extends JavaMascot {

@Override

public void executeAction() {

System.out.println("Punch!");

}}public class Juggy extends JavaMascot {

@Override

public void executeAction() {

System.out.println("Fly!");

}}public class JavaMascotTest {

public static void main(String... args) {

JavaMascot dukeMascot = new Duke();

JavaMascot juggyMascot = new Juggy();

dukeMascot.executeAction();

juggyMascot.executeAction();

}}

Punch!Fly!

多态性的接口和继承

借助此Java Challenger,我们将致力于多态性与继承之间的关系。 要记住的主要事情是多态性需要继承或接口实现。 你可以在下面的示例中看到这一点,其中包括Duke和

由于其特定的实现方式,Duke和Juggy的动作都将被执行。

方法是否重载了多态性?

许多程序员对多态与方法重写和方法重载之间的关系感到困惑。 实际上,只有方法重载才是真正的多态性。 重载使用相同的方法名称,但参数不同。 多态性是一个广义术语,因此始终会有关于该主题的讨论。

多态性的目的是什么?

使用多态的最大优点和目的是将客户端类与实现代码分离。 客户端类无需进行硬编码,而是接收实现以执行必要的操作。 这样,客户端类就足够了解执行其动作的知识,这是松耦合的示例。

为了更好地了解多态的目的,请看一下

public abstract class SweetProducer {

public abstract void produceSweet();}public class CakeProducer extends SweetProducer {

@Override

public void produceSweet() {

System.out.println("Cake produced");

}}public class ChocolateProducer extends SweetProducer {

@Override

public void produceSweet() {

System.out.println("Chocolate produced");

}}public class CookieProducer extends SweetProducer {

@Override

public void produceSweet() {

System.out.println("Cookie produced");

}}public class SweetCreator {

private List sweetProducer;

public SweetCreator(List sweetProducer) {

this.sweetProducer = sweetProducer;

}

public void createSweets() {

sweetProducer.forEach(sweet -> sweet.produceSweet());

}}public class SweetCreatorTest {

public static void main(String... args) {

SweetCreator sweetCreator = new SweetCreator(Arrays.asList(new CakeProducer(),

new ChocolateProducer(), new CookieProducer()));

sweetCreator.createSweets();

}}

在此示例中,你可以看到SweetCreator类仅知道SweetProducer类。 它不知道每个甜食的实现。 这种分离使我们可以灵活地更新和重用我们的类,并使代码易于维护。 设计代码时,请始终寻找使代码尽可能灵活和可维护的方法。 多态性是用于这些目的的一种非常强大的技术。

提示:@Override注释使程序员有义务使用必须重写的相同方法签名。 如果未重写该方法,则将出现编译错误。

方法覆盖中的协变返回类型

如果它是协变类型,则可以更改覆盖方法的返回类型。 协变量类型基本上是返回类型的子类。 考虑一个例子:

public abstract class JavaMascot {

abstract JavaMascot getMascot();}public class Duke extends JavaMascot {

@Override

Duke getMascot() {

return new Duke();

}}

由于Duke是JavaMascot,因此我们可以在覆盖时更改返回类型。

Java核心类的多态性

我们一直在核心Java类中使用多态。 一个非常简单的示例是当我们实例化ArrayList类时,将List接口声明为一种类型:

List list = new ArrayList<>();

为了进一步讲解,请考虑使用Java Collections API且无多态性的以下代码示例:

public class ListActionWithoutPolymorphism {

// Example without polymorphism

void executeVectorActions(Vector vector) {/* Code repetition here*/}

void executeArrayListActions(ArrayList arrayList) {/*Code repetition here*/}

void executeLinkedListActions(LinkedList linkedList) {/* Code repetition here*/}

void executeCopyOnWriteArrayListActions(CopyOnWriteArrayList copyOnWriteArrayList)

{ /* Code repetition here*/}}public class ListActionInvokerWithoutPolymorphism {

listAction.executeVectorActions(new Vector<>());

listAction.executeArrayListActions(new ArrayList<>());

listAction.executeLinkedListActions(new LinkedList<>());

listAction.executeCopyOnWriteArrayListActions(new CopyOnWriteArrayList<>());}

丑陋的代码,不是吗? 想象一下要维护它! 现在来看具有多态性的相同示例

public static void main(String … polymorphism) {ListAction listAction = new ListAction();

listAction.executeListActions();}public class ListAction {

void executeListActions(List list) {

// Execute actions with different lists

}}public class ListActionInvoker {

public static void main(String... masterPolymorphism) {

ListAction listAction = new ListAction();

listAction.executeListActions(new Vector<>());

listAction.executeListActions(new ArrayList<>());

listAction.executeListActions(new LinkedList<>());

listAction.executeListActions(new CopyOnWriteArrayList<>());

}}

多态性的好处是灵活性和可扩展性。 除了创建几种不同的方法外,我们可以只声明一个接收通用List类型的方法。

在多态方法调用中调用特定方法

可以在多态调用中调用特定的方法,但是这样做会牺牲灵活性。 这是一个例子:

public abstract class MetalGearCharacter {

abstract void useWeapon(String weapon);}public class BigBoss extends MetalGearCharacter {

@Override

void useWeapon(String weapon) {

System.out.println("Big Boss is using a " + weapon);

}

void giveOrderToTheArmy(String orderMessage) {

System.out.println(orderMessage);

}}public class SolidSnake extends MetalGearCharacter {

void useWeapon(String weapon) {

System.out.println("Solid Snake is using a " + weapon);

}}public class UseSpecificMethod {

public static void executeActionWith(MetalGearCharacter metalGearCharacter) {

metalGearCharacter.useWeapon("SOCOM");

// The below line wouldn't work

// metalGearCharacter.giveOrderToTheArmy("Attack!");

if (metalGearCharacter instanceof BigBoss) {

((BigBoss) metalGearCharacter).giveOrderToTheArmy("Attack!");

}

}public static void main(String... specificPolymorphismInvocation) {

executeActionWith(new SolidSnake());

executeActionWith(new BigBoss());

}}

我们在这里使用的技术是广播或在运行时故意更改对象类型。

请注意,只有在将通用类型转换为特定类型时才可以调用特定方法。 一个很好的类比是对编译器明确地说:“嘿,我知道我在这里做什么,所以我将对象转换为特定类型并使用特定方法。”

参考上面的示例,一个重要原因是编译器拒绝接受特定的方法调用:正在传递的类可能是SolidSnake。 在这种情况下,编译器无法确保MetalGearCharacter的每个子类都声明了giveOrderToTheArmy方法。

保留关键字的实例

请注意实例化的保留字。 在调用特定方法之前,我们询问了MetalGearCharacter是否为BigBoss的“实例”。 如果不是BigBoss实例,我们将收到以下异常消息:

线程“主”中的异常java.lang.ClassCastException:com.javaworld.javachallengers.polymorphism.specificinvocation.SolidSnake无法转换为com.javaworld.javachallengers.polymorphism.specificinvocation.BigBoss

超级保留关键字

如果我们想引用Java超类的属性或方法怎么办? 在这种情况下,我们可以使用超级保留字。 例如:

public class JavaMascot {

void executeAction() {

System.out.println("The Java Mascot is about to execute an action!");

}}public class Duke extends JavaMascot {

@Override

void executeAction() {

super.executeAction();

System.out.println("Duke is going to punch!");

}

public static void main(String... superReservedWord) {

new Duke().executeAction();

}}

在Duke的executeAction方法中使用保留字super调用超类方法。 然后我们从杜克(Duke)执行特定操作。 因此,我们可以在下面的输出中看到两条消息:

Java Mascot即将执行一个动作!Duke要出拳了!

接受多态挑战!

让我们尝试一下你对多态性和继承的了解。首先,请仔细分析以下代码:

public class PolymorphismChallenge {

static abstract class Simpson {

void talk() {

System.out.println("Simpson!");

}

protected void prank(String prank) {

System.out.println(prank);

}

}

static class Bart extends Simpson {

String prank;

Bart(String prank) { this.prank = prank; }

protected void talk() {

System.out.println("Eat my shorts!");

}

protected void prank() {

super.prank(prank);

System.out.println("Knock Homer down");

}

}

static class Lisa extends Simpson {

void talk(String toMe) {

System.out.println("I love Sax!");

}

}

public static void main(String... doYourBest) {

new Lisa().talk("Sax :)");

Simpson simpson = new Bart("D'oh");

simpson.talk();

Lisa lisa = new Lisa();

lisa.talk();

((Bart) simpson).prank();

}}

你怎么看? 最终输出将是什么? 不要使用IDE来解决这个问题! 关键是要提高代码分析技能,因此请尝试自己确定输出。

了解多态

对于以下方法调用:

new Lisa().talk("Sax :)");

输出为“ I love Sax!”,这是因为我们正在向该方法传递字符串,而Lisa具有该方法。

对于下一个调用:

Simpson simpson = new Bart("D'oh");

simpson.talk();

输出将是“Eat my shorts!” 这是因为我们正在使用Bart实例化Simpson类型。

现在检查一下,这有点棘手:

Lisa lisa = new Lisa();

lisa.talk();

在这里,我们使用带有继承的方法重载。 我们没有将任何内容传递给talk方法,这就是调用Simpsontalk方法的原因。 在这种情况下,输出将是:

"Simpson!"

这里还有一个:

((Bart) simpson).prank();

在这种情况下,当我们使用new Bart(“ D'oh”);实例化Bart类时,会传递恶作剧字符串。 在这种情况下,首先将调用super.prank方法,然后是来自Bart的特定恶作剧方法。 输出将是:

"D'oh""Knock Homer down"

视频挑战! 调试Java多态性和继承

调试是完全吸收编程概念并改善代码的最简单方法之一。 在此视频中,你可以在调试和解释Java多态性挑战时继续学习:

多态性的常见错误

认为无需使用强制转换就可以调用特定方法是一个常见的错误。

另一个错误是不确定多态实例化类时将调用哪种方法。 请记住,要调用的方法是创建的实例的方法。

还要记住,方法重载不是方法重载。

如果参数不同,则无法覆盖方法。 如果返回类型是超类方法的子类,则可以更改重写方法的返回类型。

喜欢这篇文章的可以点个赞,欢迎大家留言评论,记得关注我,每天持续更新技术干货、职场趣事、海量面试资料等等

> 如果你对java技术很感兴趣也可以交流学习,共同学习进步。

不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代

文章写道这里,欢迎完善交流。最后奉上近期整理出来的一套完整的java架构思维导图,分享给大家对照知识点参考学习。有更多JVM、Mysql、Tomcat、Spring Boot、Spring Cloud、Zookeeper、Kafka、RabbitMQ、RockerMQ、Redis、ELK、Git等Java干货

关于多态性要记住什么

创建的实例将确定使用多态时将调用哪种方法。

@ Override注释使程序员有义务使用覆盖的方法; 否则,将出现编译器错误。

多态可以与普通类,抽象类和接口一起使用。

大多数设计模式取决于某种形式的多态性。

在多态子类中使用特定方法的唯一方法是使用强制转换。

可以使用多态性在代码中设计功能强大的结构。

运行测试。 这样做,你将能够掌握这个强大的概念!

a88f97fe54955dc0bf30e6ac3c597c0a.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值