关于Java三大特性之多态的总结

面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。

1.定义:

多态:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

2.实现多态的技术称为:动态绑定(dynamicbinding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

3.作用:消除类型之间的耦合关系。

4.现实中,关于多态的例子不胜枚举。比方说按下F1键这个动作,如果当前在Flash界面下弹出的就是AS3的帮助文档;如果当前在Word下弹出的就是Word帮助;在Windows下弹出的就是Windows帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。

5.下面是多态存在的三个必要条件,要求大家做梦时都能背出来!

多态存在的三个必要条件

一、要有继承;

二、要有重写;

三、父类引用指向子类对象。

6.多态的好处:

1)可替换性(substitutability):多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。

2)可扩充性(extensibility):多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。

3)接口性(interface-ability):多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。

4)灵活性(flexibility):它在应用中体现了灵活多样的操作,提高了使用效率。

5)简化性(simplicity):多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

猫狗案例代码

class Animal {
	public void eat(){
		System.out.println("eat");
	}
	public void sleep(){
		System.out.println("sleep");
	}
}
class Dog extends Animal {
	public void eat(){
		System.out.println("狗吃肉");
	}
	public void sleep(){
		System.out.println("狗站着睡觉");
	}
}
class Cat extends Animal {
	public void eat() {
		System.out.println("猫吃鱼");
	}
	public void sleep() {
		System.out.println("猫趴着睡觉");
	}
}
class Pig extends Animal {
	public void eat() {
		System.out.println("猪吃白菜");
	}
	public void sleep() {
		System.out.println("猪侧着睡");
	}
}
//针对动物操作的工具类
class AnimalTool {
	private AnimalTool(){
	}
	/*
  //调用猫的功能
  public static void useCat(Cat c) {
    c.eat();
    c.sleep();
  }
  //调用狗的功能
  public static void useDog(Dog d) {
    d.eat();
    d.sleep();
  }
  //调用猪的功能
  public static void usePig(Pig p) {
    p.eat();
    p.sleep();
  }
  */
	public static void useAnimal(Animal a) {
		a.eat();
		a.sleep();
	}
	//把所有的可能都归为动物类
}
class DuoTaiDemo2 {
	public static void main(String[] args) {
		//我喜欢猫,就养了一只
		Cat c = new Cat();
		c.eat();
		c.sleep();
		//我很喜欢猫,所以,又养了一只
		Cat c2 = new Cat();
		c2.eat();
		c2.sleep();
		//我特别喜欢猫,又养了一只
		Cat c3 = new Cat();
		c3.eat();
		c3.sleep();
		//...
		System.out.println("--------------");
		//问题来了,我养了很多只猫,每次创建对象是可以接受的
		//但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。
		//我们准备用方法改进
		//调用方式改进版本
		//useCat(c);
		//useCat(c2);
		//useCat(c3);
		//AnimalTool.useCat(c);
		//AnimalTool.useCat(c2);
		//AnimalTool.useCat(c3);
		AnimalTool.useAnimal(c);
		AnimalTool.useAnimal(c2);
		AnimalTool.useAnimal(c3);
		System.out.println("--------------");
		//我喜欢狗
		Dog d = new Dog();
		Dog d2 = new Dog();
		Dog d3 = new Dog();
		//AnimalTool.useDog(d);
		//AnimalTool.useDog(d2);
		//AnimalTool.useDog(d3);
		AnimalTool.useAnimal(d);
		AnimalTool.useAnimal(d2);
		AnimalTool.useAnimal(d3);
		System.out.println("--------------");
		//我喜欢宠物猪
		//定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用
		Pig p = new Pig();
		Pig p2 = new Pig();
		Pig p3 = new Pig();
		//AnimalTool.usePig(p);
		//AnimalTool.usePig(p2);
		//AnimalTool.usePig(p3);
		AnimalTool.useAnimal(p);
		AnimalTool.useAnimal(p2);
		AnimalTool.useAnimal(p3);
		System.out.println("--------------");
		//我喜欢宠物狼,老虎,豹子...
		//定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用
		//前面几个必须写,我是没有意见的
		//但是,工具类每次都改,麻烦不
		//我就想,你能不能不改了
		//太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?
		//改用另一种解决方案。
	}
	/*
  //调用猫的功能
  public static void useCat(Cat c) {
    c.eat();
    c.sleep();
  }
  //调用狗的功能
  public static void useDog(Dog d) {
    d.eat();
    d.sleep();
  }
  */
}

7.Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。

8.Java中多态的分类:

在java中,多态大致可以分为以下几种情况:

1)person为父类,student为子类。那么:personp=newstudent();

2)fliable为接口,bird为实现接口的类,那么:fliablef=newbird();

3)fliable为抽象类,bird为继承fliable的类,那么:fliablef=newbird();

多态时需要说明p声明为父类的引用,但他实际为子类引用。但是他只能调用父类中的方法。如果子类中的方法覆盖了父类方法,那么将调用父类方法(虚方法调用)。接口多态也是同样的,也许你会问,如果f要调用自己的方法,那岂不是出错了?其实这里也是方法的覆盖,因为实现接口的子类肯定会实现接口中的方法,所以此种情况下调用的是bird中的方法。但是如果bird有一个方法在接口中没有定义,那么f不能调用。

9.instanceof运算符:

java语言的多态机制导致了引用变量的声明类型和其实际引用对象的类型可能不一致,再结合虚方法调用规则可以得出结论:声明为同种类型的两个引用变量调用同一个方法时也可能会有不同的行为。这里就引入了instanceof运算符。

那么如果我声明了personp=newstudent();我想将p转为student的可不可以?当然可以,但是就得强制转换了(儿子想成为父亲直接来,父亲想成为儿子你就强来)。

通常在强制转换时加上instanceof来判断。

if(pinstanceofstudent){students=(student)p;}

多态贯穿于java整个学习,比如在异常处理时写catch语句,我们规定必须子类异常写在前,父类异常写在后。为什么呢?原因就是多态了。我们的catch语句格式:catch(Exceptione)。java程序在产生异常时会自动生成一个异常对象,如果先产生一个子类异常,并且父类异常写在前,那么根据多态肯定会执行此catch语句,执行完一条catch语句后将会跳出。

10.实例:

关于JAVA的多态性虽然自己也不是很懂,但是下面的这个例子让我理解了一些:

class A
{
	public String show(D obj)...{
		return ("A and D");
	}
	public String show(A obj)...{
		return ("A and A");
	}
}
class B extends A
{
	public String show(B obj)...{
		return ("B and B");
	}
	public String show(A obj)...{
		return ("B and A");
	}
}
class C extends B{
}
class D extends B{
}
class E
{
	public static void main(String [] args)
	   {
		A a1 = new A();
		A a2 = new B();
		B b = new B();
		C c = new C();
		D d = new D();
		System.out.println(a1.show(b));
		//①
		System.out.println(a1.show(c));
		//②
		System.out.println(a1.show(d));
		//③
		System.out.println(a2.show(b));
		//④
		System.out.println(a2.show(c));
		//⑤
		System.out.println(a2.show(d));
		// ⑥
		System.out.println(b.show(b));
		//⑦
		System.out.println(b.show(c));
		//⑧
		System.out.println(b.show(d));
		//⑨
	}
}

(三)答案

       ①  A and A
       ②  A and A
       ③  A and D
       ④  B and A
       ⑤  B and A
       ⑥  A and D
       ⑦  B and B
       ⑧  B and B
       ⑨  A and D

****有个好心人的解答****

该问题的关键有两点:

一是子类与父类的关系,二是重载方法的调用问题。

子类对象可以直接当成父类对象使用,但反过来就不可以。举例来说,人是父类,学生是人的子类,所以学生对象一定具备人对象的属性,但是人对象就未必具有学生对象的特性。所以学生对象可以当做人对象来使用,但是人对象就不能当做学生对象使用。注意当把子类对象当成父类对象使用时,子类对象将失去所有的子类特性,只保留与父类同名的属性和方法(同名方法不仅是函数名相同,而且参数类型也要一样,否则不予保留)。

一个类中如果定义了重载的方法,则系统在调用方法时,会根据参数的类型自动选择调用合适的方法。

1)a1.shows(b),在A中没有含有B类参数的方法,但是含有A类参数的方法,根据子类对象父类可用的原则,所以调用方法

publicStringshow(Aobj)...{return("AandA");}

2)a1.show(c),C类是B类的子类,而B类又是A类的子类,所以C类对象可以当制作A类对象使用。结果同上。

3)a1.show(d),根据参数类型直接调用A中的方法

publicStringshow(Dobj)...{

return("AandD");}

4)a2.show(b),a2本来是一个B对象,但是将其赋给了A类变量,所以a2只保留了与父类A同名的属性和方法。a2.show(b)调用B类中的保留的与父类同名同参方法

public String show(A obj)...{
return ("B and A");
}

5) a2.show(c),B类的保留方法中没有C类参数方法,但是有含有C的父类B的参数方法,所以调用的方法
public String show(A obj)...{
return ("B and A");
}

我觉得这样解释更合理:a2本来是类B的一个对象,但是又将值赋给了类A,C是B的子类,B是A的子类,因此a2保留了类B中与A同名的属性和方法。

6) a2.show(d),调用的是A类中的
public String show(D obj)...{
return ("A and D");
}

7) b.show(b),调用B类中的

public String show(B obj)...{
return ("B and B");
}

8) b.show(c),B类中没有C类参数的方法,但是有B类参数的方法,所以调用方法

public String show(B obj)...{
return ("B and B");
}

9) b.show(d),解释同8

总结

以上就是本文关于Java多态性的总结的全部内容,希望对大家有所帮助。有什么问题可以随时留言,期待您的宝贵意见!

(0)

相关推荐

  • 深入理解Java三大特性中的多态

    Java三大特性 面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承是为了重用父类代码.两个类若存在IS-A的关系就可以使用继承.,同时继承也为实现多态做了铺垫.那么什么是多态呢?多态的实现机制又是什么?请看我一一为你揭开: 所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,

  • 关于Java三大特性之多态的总结

    面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 1.定义: 多态:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行为方式.(发送消息就是函数调用) 2.实现多态的技术称为:动态绑定(dynamicbinding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法. 3.作用:消除类型之间的耦合关系. 4.现实中,关于多态的例子不胜枚举.比方说按下F1

  • Java面向对象三大特性及多态解析

    大家好,本文将会给大家带来Java多态. 以上就是本次学习的6大任务.我们依次来看. 1 Object类 Object类是所有Java类的根基类. 如果在类的声明中未使用extends关键字指明其基类,则默认基类为Object类. class Person{ } 等价于 class Person extends Object{ } 1.对象的实例化过程 实例化一个类是从最顶级的超类开始实例化的, 是一层一层的包裹结构. "先父类后子类,先静态后成员". ⑴toString方法 toSt

  • Java三大特性-封装知识小结

    最近有个朋友说想要说最近在学java,他对面向对象的编程语言的时候还是有些不明白,为了帮他能更快地"转型",我就写了这篇文章.因为从上层建筑层面而言.所有的面向对象编程语言的思路都是差不多的,而这三大特性,则是思路中的支柱点,接下来我就重点讲解了一下java三大特性. 面向对象的编程语言,拥有三大特性,分别是:"封装","继承","多态". 封装 在面向对象编程中,封装封装(encapsulation)从字面上来理解就是包装的

  • Java三大特性之继承详解

    目录 概述 由来 定义 好处 继承的格式 继承后的特点—成员变量 成员变量不重名 成员变量重名 继承后的特点—成员方法 成员方法不重名 成员方法重名—重写(Override) 重写的应用 注意事项 继承后的特点—构造方法 概述 由来 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可.如图所示: 其中,多个类可以称为子类,单独那一个类称为父类.超类(superclass)或者基类. 继承描述的是事物之间的所属关系,这种关系是: i

  • Java三大特性之封装详解

    目录 封装概述 概述 原则 封装的步骤 封装的操作—private关键字 private的含义 private的使用格式 封装优化1—this关键字 this的含义 this使用格式 封装优化2—构造方法 构造方法的定义格式 注意事项 标准代码—JavaBean 封装概述 概述 面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改. 封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问.要访问该类的数据,必须通过指定的方式.适当的封装可

  • 教你如何正确了解java三大特性!!!!

    目录 继承与多态 一.包 二.继承 三:重载和重写 3.1重载(Overload) 3.2 重写 四:多态 4.1 多态的转型 4.2 instanceof 总结 继承与多态 本章讲解面向对象的三大特性:封装,继承,多态. 一.包 Java定义了一种名字空间,称之为包:package.一个类总是属于某个包,类名(比如Person)只是一个简写,真正的完整类名是 包名.类名.例如:apple 类放在包 banana 里面 完整类名是:banana.apple. 自定义包的语法: package<

  • Java轻松掌握面向对象的三大特性封装与继承和多态

    目录 1.封装 1.介绍 2.封装的理解和好处 3.封装的实现步骤 2.继承 1.介绍 2.继承的基本语法 3.继承的使用细节 3.super关键字 1.基本介绍 2.基本语法 3.细节与好处 4.super与this的比较 4.方法重写 1.基本介绍 2.注意事项与使用细节 3.重载与重写的比较 3.多态 1.基本介绍 2.具体体现 1.方法的多态 2.对象的多态(重点) 3.多态注意事项和细节讨论 1.多态的前提 2.属性 3.instance of 4.多态的向上转型 5.多态的向下转型

  • Java超详细讲解三大特性之一的多态

    目录 多态性 instanceof 关键字的使用 ==和equals()区别 object类中toString()的使用 static关键字的使用 总结 多态性 1理解多态性:可以理解为一个事物的多种形态. 2何为多态性:对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用) 3多态的使用:虚拟方法调用,有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法,多态性的使用前提:类的继承关系,方法的重写,总结:编译,看左边,运行,

  • Java超详细讲解三大特性之一的封装

    目录 封装 封装的概念 Java中的包 java中类的成员-构造器 java中的this关键字 总结 说到面向对象则不得不提面向对象的三大特征:封装,继承,多态.那么今天就和大家先来介绍什么是封装. 封装 封装的概念 将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问. 为什么需要封装? 当我们创建一个类的对象后,我们可以通过“对象.属性”的方式,对对象的属性进行赋值.这里赋值操作要受到 属性的数据类型和存储范围的制约.除此之外,没有其他制约

随机推荐