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. keepalived的配置详解(非常详细)

    keepalived的配置详解(非常详细) 2017-01-22 15:24 2997人阅读 评论(0) 收藏 举报  分类: 运维学习(25)    转载自:http://blog.csdn.net ...

  2. Django 配置总结

    配置 app urls 项目下的urls.py from django.conf.urls import url,include urlpatterns = [ url(r'^BookApp/', i ...

  3. Unigui的Grid添加汇总栏

  4. mysql实战优化之九:MySQL查询缓存总结

    mysql Query Cache 默认为打开.从某种程度可以提高查询的效果,但是未必是最优的解决方案,如果有的大量的修改和查询时,由于修改造成的cache失效,会给服务器造成很大的开销. mysql ...

  5. Java-Runoob-高级教程-实例-数组:08. Java 实例 – 数组填充

    ylbtech-Java-Runoob-高级教程-实例-数组:08. Java 实例 – 数组填充 1.返回顶部 1. Java 实例 - 数组填充  Java 实例 以下实例我们通过 Java Ut ...

  6. 学习笔记之IKM C++ 11

    https://github.com/haotang923/interview/tree/master/IKM Q1. If most of the calls to function foo() b ...

  7. java自定义事件机制分析

    import java.util.ArrayList; import java.util.EventListener; import java.util.EventObject; import jav ...

  8. webpack(5)--Resolve

    Resolve webpack在启动后会从配置的入口模块触发找出所有依赖的模块,Resolve配置webpack如何寻找模块对应的文件.webpack内置JavaScript模块化语法解析功能,默认会 ...

  9. ORM Nhibernet 框架的 CRUD 操作

    Nhibernet 的基本语法: private ISession _session; public ISession Session { set { _session = value; } } pu ...

  10. LaunchFaster 启动器工具 - 类似 Rolan 和音速启动的图标式快捷启动软件

    LaunchFaster 启动器是本人近期编写的一款windows平台上快速启动应用的开源工具软件. LaunchFaster 启动器是一款类似于 Rolan 和 音速启动 和 Lily 的图标形式的 ...