Java学习笔记(十一)面向对象---多态
多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接受自己的子类对象。
代码体现
abstract class Animal {
public abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("eat fish");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("eat bone");
}
}
class Monkey extends Animal {
@Override
public void eat() {
System.out.println("eat banana");
}
}
public class Demo {
public static void main(String[] args) {
/*
Animal c = new Cat();
function(c);
*/
function(new Cat());
/*
Animal d = new Dog();
function(d);
*/
function(new Dog());
/*
Animal m = new Monkey();
function(m);
*/
function(new Monkey());
}
public static void function(Animal a) {
a.eat();
}
}
运行结果
eat fish
eat bone
eat banana
多态的前提
必须是类与类之间有关系。要么是继承关系,要么实现。
存在复写关系。
多态利弊
利处
多态的出现大大地提高了程序的拓展性。
弊端
提高了拓展性,但是只能使用父类的引用访问父类中的成员,不能预先访问子类的成员(因为子类这时还不存在)。
多态-示例
abstract class Student {
public void eat() {
System.out.println("eat rice");
}
public abstract void study();
}
class StudentToDo {
public void Do(Student s) {
s.eat();
s.study();
}
}
class StudentClass1 extends Student {
@Override
public void eat() {
System.out.println("eat steak");
}
@Override
public void study() {
System.out.println("study English");
}
}
class StudentClass2 extends Student {
@Override
public void study() {
System.out.println("study Chinese");
}
}
class StudentClass3 extends Student {
@Override
public void study() {
System.out.println("study Japanese");
}
}
public class Demo2 {
public static void main(String[] args) {
StudentToDo std = new StudentToDo();
std.Do(new StudentClass1());
std.Do(new StudentClass2());
std.Do(new StudentClass3());
}
}
运行结果:
eat steak
study English
eat rice
study Chinese
eat rice
study Japanese
多态的出现 代码中的特点(多态使用的注意事项)
多态中成员函数的特点
在编译时期,参阅引用类型变量所属的类中是否有调用的方法,如果有编译通过,如果没有编译失败。
在运行时期,参阅对象所属的类中是否有调用的方法。
简单总结:成员函数在多态调用时,编译看左边,运行看右边。
class Fu {
void method1() {
System.out.println("Fu_Method_1");
}
void method2() {
System.out.println("Fu_Method_2");
}
}
class Zi extends Fu {
@Override
void method1() {
System.out.println("Zi_Method_1");
}
void method3() {
System.out.println("Zi_Method_3");
}
}
public class Demo3 {
public static void main(String[] args) {
Fu f =new Zi();
f.method1();
f.method2();
//f.method3(); 对于引用类型f所属的类Fu中没有method3()方法,所以编译会不通过。
}
}
运行结果:
Zi_Method_1
Fu_Method_2
多态中成员变量的特点
无论编译还是运行,都参考左边(引用型变量所属的类)
class Fu {
int num = 1;
}
class Zi extends Fu {
int num = 2;
}
public class Demo4 {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num); //参考左边
Zi z= new Zi();
System.out.println(z.num);
}
}
运行结果:
1
2
多态中静态成员函数(变量)的特点
无论编译还是运行,都参考左边。
静态类型,静态绑定。
非静态类型,动态绑定。
class Fu {
static void method1() {
System.out.println("Fu_Method_1");
}
}
class Zi extends Fu {
static void method1() {
System.out.println("Zi_Method_1");
}
}
public class Demo5 {
public static void main(String[] args) {
Fu f = new Zi();
f.method1();
Zi z = new Zi();
z.method1();
}
}
运行结果:
Fu_Method_1
Zi_Method_1
多态-转型
abstract class Animal {
public abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("eat fish");
}
public void CatchMouse() {
System.out.println("CatchMouse");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("eat bone");
}
public void GuardHouse() {
System.out.println("GuardHouse");
}
}
class Monkey extends Animal {
@Override
public void eat() {
System.out.println("eat banana");
}
public void PlayBall() {
System.out.println("Play Ball");
}
}
public class Demo1 {
public static void main(String[] args) {
function(new Cat());
function(new Dog());
function(new Monkey());
}
public static void function(Animal a) {
a.eat();
if (a instanceof Cat) { //instanceof关键字用于判断所属类型
Cat c = (Cat)a; //向下转型
c.CatchMouse();
} else if (a instanceof Dog) {
Dog d = (Dog)a; //向下转型
d.GuardHouse();
} else {
Monkey m = (Monkey)a;//向下转型
m.PlayBall();
}
}
}
运行结果:
eat fish
CatchMouse
eat bone
GuardHouse
eat banana
Play Ball
多态的应用
以电脑主板为例的示例
分析电脑主板要考虑到拓展性,使用了pci接口,板卡(声卡,网卡等)和主板都遵循pci接口。
interface Pci {
public void open();
public void close();
}
class MainBoard {
public void run() {
System.out.println("Main Board run");
}
public void usePci(Pci p){ //接口类型指向自己的子类对象
if(p != null){ //加入判断防止空指针
p.open();
p.close();
}
}
}
class Netcard implements Pci {
@Override
public void open() {
System.out.println("Netcard open");
}
@Override
public void close() {
System.out.println("Netcard close");
}
}
class Soundcard implements Pci {
@Override
public void open() {
System.out.println("Soundcard open");
}
@Override
public void close() {
System.out.println("Soundcard close");
}
}
public class Demo6 {
public static void main(String[] args) {
MainBoard mb = new MainBoard();
mb.run();
mb.usePci(null);
mb.usePci(new Netcard());
mb.usePci(new Soundcard());
}
}
运行结果
Main Board run
Netcard open
Netcard close
Soundcard open
Soundcard close
Java学习笔记(十一)面向对象---多态的更多相关文章
- Java学习笔记之---面向对象
Java学习笔记之---面向对象 (一)封装 (1)封装的优点 良好的封装能够减少耦合. 类内部的结构可以自由修改. 可以对成员变量进行更精确的控制. 隐藏信息,实现细节. (2)实现封装的步骤 1. ...
- Java学习笔记之面向对象、static关键字
一周Java学习总结 今天就总结理清一下关于面向对象和面向过程的程序设计的一些不同特点,以及讲下static关键字. 面向对象 现在接触的Java是面向对象的,现在的程序开发几乎都是以面向对象为基础的 ...
- Java 学习笔记(4)——面向对象
现在一般的语言都支持面向对象,而java更是将其做到很过分的地步,java是强制使用面向对象的写法,简单的写一个Hello Word都必须使用面向对象,这也是当初我很反感它的一点,当然现在也是很不喜欢 ...
- Java学习笔记:03面向对象-接口_多态
1.类的概念 一堆具有共同的成员变量(属性)和成员方法(功能)对象的集合 2.接口的概念 接口是功能的集合,就是方法的集合 接口中只能定义方法,不能定义普通的成员变量 而且接口中的成员方法,必须是抽象 ...
- 疯狂java学习笔记之面向对象(五) - 封装、继承、多态
一.封装: 封装的概念: - 合理的隐藏:隐藏不想被外界操作的Field.方法.构造器 - 合理的暴露:一般就是希望给别人调用的方法 e.g:显示器(按键暴露出来操作,但实际的东西/细节方法被隐藏起来 ...
- Java学习笔记--继承和多态(中)
1.通过继承来开发超类(superclass) 2.使用super 关键词唤起超类的构造方法 3.在超类中覆盖方法 4.区分override和overload 5.在Object类中探索toStrin ...
- 【原】Java学习笔记019 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 仔细想一想,Ani ...
- Java精选笔记_面向对象(多态、异常)
多态 概述 可以理解为事物存在的多种体现形态.同样的引用调用同样的方法却做了不同的事情 多态的本质是:一个程序中同名的不同方法. 多态的体现 父类的引用指向子类的对象,父类的引用接收子类的对象. 多态 ...
- Java学习笔记--继承和多态(上)
1.通过继承来开发超类(superclass) 2.使用super 关键词唤起超类的构造方法 3.在超类中覆盖方法 4.区分override和overload 5.在Object类中探索toStrin ...
随机推荐
- 基于WEB的车票预订信息系统设计
注册登录界面 用户输入网址以后,用自己的手机号作为账号,然后输入自己想设置的密码注册一个号,然后点击注册,即注册登录.如图5.1所示: 图5.1 车票预订信息系统注册登录界面 5.2 车票查询界面 ...
- Dynamics CRM 365中结合注释和WebApi实现图片上传
首先需要在实体上使用注释,然后在窗体上引用WebResource. WebResource的代码: <!DOCTYPE html> <html> <head> &l ...
- 克里金插值 调用matlab工具箱
克里金插值 克里金插值是依据协方差函数对随机过程或随机场进行空间建模和插值的回归算法. 克里金插值法的公式为: 式中为待插入的各点的重金属污染值,为已知点的重金属污染值,为每个点的权重值. 用BLUP ...
- Codeforces Round #620 (Div. 2) D
构造一个排列,要求相邻之间的数满足给定的大小关系,然后构造出两个序列,一个序列是所有可能的序列中LIS最长的,一个所有可能的序列中LIS最短的 最短的构造方法:我们考虑所有单调递增的部分,可以发现要让 ...
- Wannafly Camp 2020 Day 3F 社团管理 - 决策单调性dp,整体二分
有 \(n\) 个数构成的序列 \({a_i}\),要将它划分为 \(k\) 段,定义每一段的权值为这段中 \((i,j) \ s.t. \ i<j,\ a_i=a_j\) 的个数,求一种划分方 ...
- script标签引入脚本的引入位置与效果
用script标签引入脚本的引入位置大致有两种情况: 1,在head中引入: 2,在body末尾引入: 浏览器由上到下解析代码,正常情况下,先解析head中的代码,在解析body中的代码:放在head ...
- afl-fuzz技术初探
afl-fuzz技术初探 转载请注明出处:http://www.cnblogs.com/WangAoBo/p/8280352.html 参考了: http://pwn4.fun/2017/09/21/ ...
- A*模板(求K短路)(POJ2449)
A*是bfs的优化,IDA*是dfs的优化 A*算法: 为启发式算法中很重要的一种,被广泛应用在最优路径求解和一些策略设计的问题中.而A*算法最为核心的部分,就在于它的一个估值函数的设计上: f(n) ...
- PGET,一个简单、易用的并行获取数据框架
使用场景 当我们的服务收到一个请求后,需要大量调用下游服务获取业务数据,然后对数据进行转换.计算后,响应给请求方. 如果我们采用串行获取下游数据,势必会增加响应时长,降低接口的qps.如果是并行获取下 ...
- Apache Tomcat配置启动
文章目录 前提 配置启动Tomcat 遇到的问题 端口被占用 解决方案 淇℃伅 特别感谢 前提 已经安装Java JDK 已经配置将Java JDK的bin目录添加至环境变量Path 已经配置JAVA ...