package com.bjsxt.oop.polymorphism;

 public class Animal {
public void voice(){
System.out.println("动物叫声");
}
}
class Cat extends Animal{
public void voice(){
System.out.println("喵喵喵");
}
}
class Dog extends Animal{
public void voice(){
System.out.println("汪汪汪");
}
}
class Pig extends Animal{
public void voice(){
System.out.println("吭哧吭哧");
}
}
 package com.bjsxt.oop.polymorphism;

 /**引用变量的2中类型
* 1,编译时类由声明事类型决定
* 2,运行时类型 由实际传入的对象类型决定
*
*
* 三个必要条件
* 要有继承
* 要有重写
* 父类引用指向子类对象
* @author Administrator
*
*/
public class Test {
/*如果没有多态,我们需要把每个子类的叫的方法写一遍,重载动物叫声方法 显然不方便
public static void testAnimalVoice(Cat c){
c.voice();
public static void testAnimalVoice(Dog d){
d.voice();
public static void testAnimalVoice(Pig p){
p.voice();
}*/
//使用多态就很简单 编译时类由声明事类型决定
public static void testAnimalVoice(Animal a){
a.voice();
}
public static void main(String[] args) {
//运行时类型 由实际传入的对象类型决定
/*父类引用指向子类对象
Cat c = new Cat();
Animal a = c;
我们写成下面这样
*/
Animal c = new Cat();
Animal d = new Dog();
Animal p = new Pig();
testAnimalVoice(c);
testAnimalVoice(d);
testAnimalVoice(p); }
}

我们试着重写方法

我们每一个动物,重写一个属于自己的方法;

 package com.bjsxt.oop.polymorphism;

 public class Animal {
public void voice(){
System.out.println("动物叫声");
}
}
class Cat extends Animal{
public void voice(){
System.out.println("喵喵喵");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void voice(){
System.out.println("汪汪汪");
}
public void seeDoor(){
System.out.println("狗看门");
}
}
class Pig extends Animal{
public void voice(){
System.out.println("吭哧吭哧");
}
public void sleep(){
System.out.println("猪在睡觉");
}
}
class Tiger extends Animal{
public void voice(){
System.out.println("吼吼吼");
}
public void eat(){
System.out.println("老虎在吃饭");
}
}

我们试着 调用一下

package com.bjsxt.oop.polymorphism;

/**引用变量的2中类型
* 1,编译时类由声明事类型决定
* 2,运行时类型 由实际传入的对象类型决定
*
*
* 三个必要条件
* 要有继承
* 要有重写
* 父类引用指向子类对象
* @author Administrator
*
*/
public class Test {
/*如果没有多态,我们需要把每个子类的叫的方法写一遍,重载动物叫声方法 显然不方便
public static void testAnimalVoice(Cat c){
c.voice();
public static void testAnimalVoice(Dog d){
d.voice();
public static void testAnimalVoice(Pig p){
p.voice();
}*/
//使用多态就很简单 编译时类由声明事类型决定
public static void testAnimalVoice(Animal a){
a.voice();
}
public static void main(String[] args) {
//运行时类型 由实际传入的对象类型决定
/*父类引用指向子类对象
Cat c = new Cat();
Animal a = c;
我们写成下面这样
*/
Animal c = new Cat();
Animal d = new Dog();
Animal p = new Pig();
Animal t = new Tiger();
testAnimalVoice(c);
testAnimalVoice(d);
testAnimalVoice(p);
testAnimalVoice(t); //我们在我们重写了很多类的方法 我们试着调一下
//c.cathMouse(); 报错The method cathMouse() is undefined for the type Animal
//咦?说我们的抓老鼠的方法在Animal类里没定义 我让猫抓老鼠和你Animal有什么关系? 原来编译器不通过(编译器没那么智能,你传什么对象他就是啥了你得声明)是因为
//编译器 只认证不认人 比如 你掉方法 c.cathMouse(); c是什么呢? Animal c = new Cat(); c的前面 类型写的是Animal 你就是Animal类型
//既然 我们想让猫抓老鼠 那么 就强制转型被
//在编译器的角度看c是Animal 类型我们强制转换(Cat)然后 用 新的Cat c1来接受新的对象
Cat c1 = (Cat)c;
c1.catchMouse();
Dog d1=(Dog)d;
d1.seeDoor();
Pig p1 = (Pig)p;
p1.sleep();
Tiger t1 = (Tiger)t;
t1.eat();
//能把老虎转成猫吗?
Cat c2 = (Cat)t;
c2.catchMouse();//通过了,再次证明编译器死板
//跑起来报错Exception in thread "main" java.lang.ClassCastException: com.bjsxt.oop.polymorphism.Tiger cannot be cast to com.bjsxt.oop.polymorphism.Cat
//at com.bjsxt.oop.polymorphism.Test.main(Test.java:59)
//老虎不能转成猫
}
}

打印一下

喵喵喵
汪汪汪
吭哧吭哧
吼吼吼
猫抓老鼠
狗看门
猪在睡觉
老虎在吃饭

显然,这么做比较繁琐 ,不如做个逻辑判断,是啥就是啥。

     //由于最后面的对象转型太繁琐,索性做一个逻辑判断
public static void testAnimalVoice(Animal a){
a.voice();
if(a instanceof Cat){
((Cat)a).catchMouse();
}else if(a instanceof Dog){
((Dog)a).seeDoor();
}else if(a instanceof Pig){
((Pig)a).sleep();
}else{
((Tiger)a).eat();
}
}

当然 里面也得做强制转换,否则,编译器不认,通不过。

     public static void main(String[] args) {
//运行时类型 由实际传入的对象类型决定
/*父类引用指向子类对象
Cat c = new Cat();
Animal a = c;
我们写成下面这样
*/
Animal c = new Cat();
Animal d = new Dog();
Animal p = new Pig();
Animal t = new Tiger();
testAnimalVoice(c);
testAnimalVoice(d);
testAnimalVoice(p);
testAnimalVoice(t);
}

打印看一下结果

喵喵喵
猫抓老鼠
汪汪汪
狗看门
吭哧吭哧
猪在睡觉
吼吼吼
老虎在吃饭

  对象转型可以使父类对象的引用可以指向子类对象,给程序带来了比较好的可扩展性:我们可以在一个方法的参数里面定义父类的引用,然后实际当中传的时候传的是子类的对象,然后我们再在方法里面判断这个传过来的子类对象到底属于哪个子类,然后再去执行这个子类里面的方法或者调用这个子类里面的成员变量,因此程序的可扩展性比单独定义好多个方法要好一些。

面向对象三大特性一一多态(polymorphism)的更多相关文章

  1. python 面向对象三大特性(封装 多态 继承)

    今天我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)注:Java和C#来说只支持面向对象编程,而python比较灵活即支持面 ...

  2. Java中面向对象三大特性之——多态

    多态的概述:  多态是继封装.继承之后,面向对象的第三大特性. 生活中,比如跑的动作,小猫.小狗和大象,跑起来是不一样的.再比如飞的动作,昆虫.鸟类和飞机,飞起来也是不一样的.可见,同一行为,通过不同 ...

  3. python基础(25):面向对象三大特性二(多态、封装)

    1. 多态 1.1 什么是多态 多态指的是一类事物有多种形态. 动物有多种形态:人,狗,猪. import abc class Animal(metaclass=abc.ABCMeta): #同一类事 ...

  4. C#面向对象三大特性:多态

    什么是多态 公司最近为了陶冶情操,养了几种动物(Animal),有猫(Cat).狗(Dog).羊(Sheep),这些动物都有共同的特性,会吃(Eat).会叫(Shout),但是它们吃的不同,叫的也不同 ...

  5. 《Python》 面向对象三大特性之多态、封装

    一.多态 1.什么是多态? 一个类表现出的多种状态:通过继承来实现的 在Java中的表现:在一个函数中需要给参数指定数据类型,如果这个地方可以接收两个以上类型的参数,那么这些类型应该有一个父类,这个父 ...

  6. 面向对象三大特性一一继承(inheritance)和组合(Composition)

    记住2句话(常识),像个正常人思考! 1.“  is-a ”关系 用 继承! 学生是人,学生继承人这个类, 2. “has-a ”关系 用 组合!电脑有显卡,那么我们就在计算机类中增加显卡属性来复用显 ...

  7. 面向对象三大特性一一封装(encapsulation)

    为什么要封装? 我们看电视,只要按一下开关和换台就行了.有必要了解电视的内部结构吗?有必要了解显像管吗? 封装是为了隐藏对象内部的复杂性,只对外公开简单的接口.便于外界调用,从而提高系统的可扩展性,可 ...

  8. Java基础-面向对象第三大特性之多态(polymorphism )

    Java基础-面向对象第三大特性之多态(polymorphism) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.多态概述 多态是继封装,继承之后,面向对象的第三大特性,多态的 ...

  9. [.net 面向对象编程基础] (13) 面向对象三大特性——多态

    [.net 面向对象编程基础] (13) 面向对象三大特性——多态 前面两节,我们了解了面向对象的的封装和继承特性,面向对象还有一大特性就是多态.比起前面的封装和继承,多态这个概念不是那么好理解.我们 ...

随机推荐

  1. 后台调用前台JS(查看客户端IE版本)

    1.前端代码    </form>    //注意放在form下面<script>    function readRegedit() {        var obj = n ...

  2. golang sizeof 占用空间大小

    C语言中,可以使用sizeof()计算变量或类型占用的内存大小.在Go语言中,也提供了类似的功能, 不过只能查看变量占用空间大小.具体使用举例如下. package main import ( &qu ...

  3. winform截屏

    引自 http://www.cnblogs.com/aland-liu/archive/2011/07/20/Winform.html 已经注册博客好久,一直由于工作原因没有打理.今天在网上看了一个截 ...

  4. 【用jersey构建REST服务】系列文章

    1.用Jersey构建RESTful服务1--HelloWorld http://blog.csdn.NET/kkkloveyou/article/details/21391033 2.用Jersey ...

  5. mysql binlog协议分析--具体event

    这几天在修改canal, 连接mysql和maria接收到的event有所区别 拿一个简单的insert sql来举例 mysql 会有以下几个event写入到binlog里 1.ANONYMOUS_ ...

  6. ubuntu 常用命令集锦

    一.文件/文件夹管理 ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件) ls -l 列出当前目录下文件的详细信息 cd .. 回当前目录的上一级目录 cd - 回 ...

  7. Linux防火墙(Firewalls)

    结构关系图 查看这两个防火墙文件 # cat /etc/hosts.deny # cat /etc/hosts.allow 查看Linux中防火墙的状态 某个服务是否能由tcpwraps来进行控制关键 ...

  8. python3 from Tkinter import * 和import Tkinter as tk两个区别import Tkinter

    原文https://stackoverflow.com/questions/15974787/difference-between-import-tkinter-as-tk-and-from-tkin ...

  9. Vcenter 和ESXi License过期解决办法

    Vcenter License过期解决办法 用client连接vcenter:  KEY必须用vCenter Server 5 Standard序列号如果使用使用的“vCenter Server 5 ...

  10. java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?

    在Java中,所有对象都能够被作为"监视器monitor"——指一个拥有一个独占锁,一个入口队列和一个等待队列的实体entity.所有对象的非同步方法都能够在任意时刻被任意线程调用 ...