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. LOJ 2542 「PKUWC2018」随机游走 ——树上高斯消元(期望DP)+最值反演+fmt

    题目:https://loj.ac/problem/2542 可以最值反演.注意 min 不是独立地算从根走到每个点的最小值,在点集里取 min ,而是整体来看,“从根开始走到点集中的任意一个点就停下 ...

  2. nginx搭建负载均衡

    负载均衡:针对web负载均衡简单的说就是将请求通过负债均衡软件或者负载均衡器将流量分摊到其它服务器. 负载均衡的分类如下图: 今天分享一下nginx实现负载均衡的实现,操作很简单就是利用了nginx的 ...

  3. C/C++基础----变量和基本类型

    变量和基本类型 不同平台下基本类型的字节数 类型 16位平台 32位平台 64位平台 char 1 1 1 short 2 2 2 int 2 4 4 long 4 4 8 long long / 8 ...

  4. bzoj4693: 雪中送温暖

    Description 每年的1月10日是温暖节,在这一天,化身出题人的C_SUNSHINE将会给OIer们送温暖.OIer们只要在门口放上一个 仙人掌,就能在早上的某个时刻听到门外传来一声:“开门, ...

  5. h3c端口汇聚的几种情况-S5500-S5048

    S5500和S5048E聚合的几种情况,分享下:1.S5048E用手工的话,S5500用静态方式2.S5048E用静态的话,S5500用动态方式3.S5048E和S5048E聚合的话,用相同方式即可. ...

  6. Linux修改本地时间

    1.Linux时间调整 1)安装ntp(目的同步时间) yum install ntp 2)修改文件 vi /etc/ntp.conf 添加 server ntp.sjtu.edu.cn perfer ...

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

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

  8. 浅析HttpCient

    HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 JDK 的 java.net 包中已经提供了 ...

  9. Ubuntu14.04下hadoop-2.6.0单机配置和伪分布式配置

    需要重新编译的教程:http://blog.csdn.net/ggz631047367/article/details/42460589 在Ubuntu下创建hadoop用户组和用户 hadoop的管 ...

  10. 关于sencha touch在华为、红米等部分手机下hide事件失效,msgbox无法关闭的解决方案(已更新最新解决方案)

    (急着解决问题的同学可以直接跳最底部查看最终的解决方案) 问题描述 因为前段时间抢到了华为荣耀3c,所以做项目的时候就用荣耀3c测试了一下项目, 结果发现在华为的emotion ui上sencha t ...