1. 多态

1.1  概述

某一个事务,在不同环境下表现出来的不同状态

如:中国人可以是人的类型,中国人 p = new  中国人();同时中国人也是人类的一份,也可以把中国人称为人类,人类  d  =  new  中国人()

1.2 多态的前提和体现

  1. 有继承关系
  2. 父类的引用指向子类的对象
  3. 有方法的重写

1 public class Test {
2 public static void main() {
3 Person p = new Teacher(); // 父类的引用指向子类的对象
4 }
5 }
6 class Person{}
7 class Teacher extends Person{}

如前几天学习,创建对象应该是如下

Person p = new Person();
Teacher t = new Teacher();

但是现在写成如下,便是父类的引用指向子类的对象

Person p = new Teacher(); //按以前学习此处的p的引用指向应该为new Person

1.3 两种转型

  向上转型:Person  p = new  Teacher();

  向下转型:Teacher t = (Teacher)p;

1.4  调用关系

  1. 同名成员变量:  父类的

  2. 同名静态方法:  父类的(所以说静态方法不能叫重写,因为调用还是会调用父类的方法,子类中定义的方法不会被调用)

  3. 同名静态变量:  父类的

  4. 同名成员方法:  子类的

  5.子类独有:     不能调用

  6.父类独有:     调用父类

案例

class Animal {
int num = 10;
static int age = 20;
public void eat() {
System.out.println("动物吃饭");
}
public static void sleep() {
System.out.println("动物在睡觉");
}
public void run(){
System.out.println("动物在奔跑");
}
}
class Cat extends Animal {
int num = 80;
static int age = 90;
String name = "tomCat";
public void eat() {
System.out.println("猫吃饭");
}
public static void sleep() {
System.out.println("猫在睡觉");
}
public void catchMouse() {
System.out.println("猫在抓老鼠");
}
} class AnimalTest {
public static void main(String[] args) {
Animal am = new Cat();//向上转型
am.eat(); // 猫吃饭
Animal.sleep();// 动物在睡觉
am.run(); //动物在跑步
System.out.println(am.num);// 10
System.out.println(Animal.age);// 20
am.catchMouse();// 报错,可知子类独有的方法不能被调用
System.out.println(am.name);// 报错,可知子类独有的变量不能被调用
Cat ct = (Cat)am; //向下转型,调用时就调用子类自己的属性或方法,若没有相关事务就去父类中找
ct.eat();// 猫吃饭
Cat.sleep(); // 猫在睡觉
ct.run(); // 动物在跑步,可见子类中没有的方法会去父类中找
ct.catchMouse(); // 猫在抓老鼠
}
}

练习,如何将三个不同类型的蛋放一个篮子里(如鸡蛋,鸭蛋,鹅蛋)

创建3个蛋,分别为鸡蛋,鸭蛋,鹅蛋

 1 public class EggDemo {
2 public static void main(String[] args) {
3 HenEgg egg1 = new HenEgg();
4 DuckEgg egg2 = new DuckEgg();
5 GooseEgg egg3 = new GooseEgg();
6 }
7 }
8 class HenEgg{String name;}
9 class DuckEgg{String name;}
10 class GooseEgg{String name;}

比如,将3个蛋放进鸡蛋数组,发现并不能实现,如下图

所以,若没有多态,就实现不了一个篮子放三个鸡蛋,下面是利用多态来解决这个放鸡蛋的问题

public class EggDemo {
public static void main(String[] args) {
Egg egg1 = new HenEgg();
Egg egg2 = new DuckEgg();
Egg egg3 = new GooseEgg();
Egg[] eggs = new Egg[]{egg1,egg2,egg3};
}
}
class Egg{String name;}
class HenEgg extends Egg{String name;}
class DuckEgg extends Egg{String name;}
class GooseEgg extends Egg{String name;}

结合这个例子理解什么是多态?

多态就是多种形态,有时候是蛋,有时候是鸡蛋,所以是多套

Egg egg1 = new HenEgg();   等号左边是蛋右边是鸡蛋

什么时候是鸡蛋,什么时候是蛋呢?

在调用成员方法时,调用的是子类方法,这个时候就是鸡蛋,除了成员方法以外,调用的都是父类的事务,所以是蛋

多态的应用(同样是这个例子)

 1 public class EggDemo {
2 public static void main(String[] args) {
3 Egg egg1 = new HenEgg();
4 Egg egg2 = new DuckEgg();
5 Egg egg3 = new GooseEgg();
6 Egg[] eggs = new Egg[]{egg1,egg2,egg3};
7 // egg1.born();
8 // egg2.born();
9 // egg3.born();
10 test(egg1);
11 }
12 public static void test(Egg e) { // 将参数类型定义为父类,传哪个子类就调用哪个子类方法,这样更加灵活,无多态的话每次就需要创建一个对象来实现
13 e.born();
14 }
15 }
16 class Egg{
17 String name;
18 public void born() {
19 System.out.println("生小*");
20 }
21 }
22
23 class HenEgg extends Egg{
24 String name;
25 public void born() {
26 System.out.println("生小鸡");
27 }
28 }
29 class DuckEgg extends Egg{
30 String name;
31 public void born() {
32 System.out.println("生小鸭");
33 }
34 }
35 class GooseEgg extends Egg{
36 String name;
37 public void born() {
38 System.out.println("生小鹅");
39 }
40 }

1.5  多态的访问特点

面试题1

子类独有的方法不能被调用

面试题2

结果是    我爱你

1..6 多态的好处和弊端

1.多态的好处 :

提高了程序的维护性(由继承保证)

提高了程序的扩展性(由多态保证)

2. 多态的弊端

不能访问子类特有的功能

 2.  抽象

1.1  抽象类的概述:

回想前面我们的猫狗案例,提取出了一个动物类。并且我们在前面也创建过了动物对象,其实思想是不对的。为什么呢?因为,我说动物,你知道我说的是什么动物嘛?只有看到了具体的动物,你才知道,这是什么动物。所以说,动物本身并不是一个具体的事物,而是一个抽象的事物。只有真正的猫,狗才是具体的动物。同理,我们也可以推想,不同的动物睡觉的方式应该是不一样的,所以,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。在java中,一个没哟方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

1.2 细节

用abstract 修饰的类:

(1)抽象方法格式:

    abstract 修饰符返回值类型方法名(参数列表);

(2)抽象类的定义格式:

   abstract class 类名{}

1. 抽象类中可以没有抽象方法,有抽向方法的类一定是抽象类
 2. 抽象类不能创建对象,需要使用子类向上转型
 3. 抽象的子类要么实现抽象类中所有的抽象方法,要么自己是一个抽象类
 4. 抽象类有构造方法(为了让子类能够调用,完成数据的初始化)
 5. abstract 不能和final 共存

案例

抽象类不能创建对象,下面第三行代码会报错

1 public class AbstractDemo {
2 public static void main(String[] args) {
3 Animal a = new Animal();
4 }
5 }
6 // 动物抽象类
7 abstract class Animal{
8 abstract public void sleep();
9 }

报错如下

抽象类的子类不能有抽象方法,所以需要将这个抽象方法重写

当在定义一个继承自Animal类的Cat类时,就需要重写Animal类中的抽象方法,如下

1 // 定义猫类
2 class Cat extends Animal{
3 @Override
4 public void sleep() { //重写sleep方法
5 System.out.println("猫站着睡觉");
6 }
7 }

(3)抽象类的成员特点

  1. 成员变量:

    可以是变量,也可以是常量

  2. 构造方法

    有构造方法,但是不能实例化(即不能创建对象),起用于子类访问父类数据的初始化

  3. 成员方法

    可以有抽象方法,限定子类必须完成某些动作

    也可以有非抽象方法,用于提高代码的复用性(如抽象类中需要额外实现一个功能,若这个类中有很多子类,用抽象方法的话,其子类都要重写这个抽象方法,若代码量特别      大,将是毁灭性的,这个时候用非抽象方法就没这个问题)

 练习

1. 定义一个抽象类形状(shape), 包含两个方法,求周长和面积

   定义一个类长方形,实现抽象类中的方法

   定义一个圆,实现抽象类中的方法

   在测试类中测试

 1 public class Exercise1 {
2 public static void main(String[] args) {
3 Shape s = new Rect(2,4);
4 Shape c = new Circle(3);
5 result(s);
6 result(c);
7 }
8 public static void result(Shape s) {
9 System.out.println("面积为:"+s.getArea());
10 System.out.println("周长为:"+s.getPerimeter());
11 }
12 }
13
14 abstract class Shape{
15 public abstract double getArea();
16
17 public abstract double getPerimeter();
18 }
19
20 class Rect extends Shape{ // 继承关系 Is a
21 double length;
22 double wide;
23 public Rect(double length,double wide){
24 this.length = length;
25 this.wide = wide;
26 }
27 @Override
28 public double getArea() { // 该重写方法的权限要比抽象类声明处的权限要高,声明处是public,所以此处只能是public
29 return length*wide;
30 }
31 public double getPerimeter() {
32 return 2*(length+wide);
33 }
34 }
35 class Circle extends Shape{
36 double r;
37 public static final double PI=3.14;
38 public Circle(double r) {
39 this.r = r;
40 }
41 public double getArea() {
42 return PI*r*r;
43 }
44 public double getPerimeter() {
45 return 2*PI*r;
46 }
47 }

2. 定义一个人,张三,男,18岁  手机  其中手机的特性为苹果X ,白色,价格是8888

此处注意点是自己定义一个手机类,当做手机的数据类型 ,即Mobile mobile;  此处为组合关系  has a

public class PersonTest {
public static void main(String[] args) {
Mobile mobile = new Mobile("苹果X","白色",8888);
Person p = new Person("张三",'男',18,mobile);
System.out.println("我的名字叫"+p.name+",性别:"+p.gender+",年龄;"+p.age+"我的手机为:"+mobile.name+",颜色为"+mobile.color+",价格为"+mobile.price);
}
}
// 定义一个Person类
class Person{
String name;
char gender;
int age;
Mobile mobile;
public Person(String name,char gender,int age,Mobile mobile) {
this.name = name;
this.gender = gender;
this.age = age;
this.mobile = mobile;
}
}
// 定义一个手机类
class Mobile{
String name;
String color;
double price;
public Mobile(String name,String color,double price) {
this.name = name;
this.color = color;
this.price = price; }
}

3.

3. 接口

接口不是类,但其与类是同一层次的事物。

3.0 接口的概述:

3.1 定义格式:

  interface  接口名{ }

public class InterfaceDemo{}
interface InterfaceA{}

3.2 注意事项

1. 接口中只能定义常量,默认public static final修饰,不能定义变量。

interface InterfaceA{
int a=10;//等价于public static final int a = 10
}

2. 接口中只能定义抽象方法(1.8之前)  默认是public abstract 修饰

 如下面代码

interface InterfaceA{
private void test(); // 报错
void test();//正确,此外写publc和abstract二者之一都是正确的,如下
//public void test(); 正确
}

注意:这种默认情况表明子类中的方法也只能用public修饰(子类重写父类中的方法,权限不能比父类中的方法低)

3. 接口本身不能创建对象,使用子类向上转型(如练习三中)

  接口的子类:实现了接口的类

  格式:class 类名  implements 接口名{}

  一个类可以实现多个接口:class 类名  implements 接口1,,接口2......{}

4.接口的子类要么实现接口中所有的抽象方法要么自己是一个抽象类

1 public class InterfaceDemo {}
2 interface InterfaceA{
3 void test();
4 }
5 class Test implements InterfaceA{
6 public void test() { //重写test()方法,此处是类,一定要加public
7 }
8 }

5. 接口中没有构造方法

6. 接口不能实现接口,只能继承接口,并且可以多继承(类实现接口,并且一个类可以实现多个接口)

如,再定义一个接口B,让其继承自InterfaceA,里面不能重写接口InterfaceA中声明的test()方法(即不能实现InterfaceA接口),会报错,如下

class 子类名  implements  接口1,接口2{ }

public class InterfaceDemo {}
interface InterfaceA{
void test();
}
interface InterfaceB {
void test1(); }
class Test implements InterfaceA,InterfaceB{// 接口的子类一定要去实现其继承接口的所有方法,否则报错
public void test() {
System.out.println("实现接口A");
}
public void test1() {
System.out.println("实现接口B");
}
}

7.从jdk1.8以后,接口中可以定义非抽象的方法,但是必须使用static或者default(不能省略)修饰

8. 一个类可以继承一个类,并且同时实现多个接口(先继承,再实现)

class 类1 extends 类2 implents 接口()//类中可以定义实现接口的方法

 3.3 面试题

 1.抽象类和接口的区别

1. 一个类可以实现多个接口,但却只能继承最多一个抽象类

2. 抽象类可以包含具体的方法,接口的所有方法都是抽象的(jdk1.8之前)

3. 抽象类可以定义常量也可以定义变量,接口只能定义常量

4. 接口的方法都是public的,抽象类的方法可以是public,protected,private或者默认的package

5. 抽象类可以定义构造函数,但接口却不能

 2.什么时候定义抽象类,什么时候定义接口?

接口是功能的扩展,抽象类是根源的扩展

如门,开门,关门应该是其固有的功能,但报警的话就只有防盗门有这个功能,其他门没有,所以报警就可以被定义为接口

 1 // 定义抽象类,其中定义开门和关门的功能
2 abstract class Door{
3 public abstract void openDoor();
4 public abstract void closeDoor();
5 }
6 //定义报警接口
7 interface Alarm{
8 public void alarm();
9 }
10 // 定义门的子类--防盗门,
11 class FDoor extends Door implements Alarm{
12 public void openDoor() {}
13 public void closeDoor() {}
14 public void alarm() {} // 实现接口中报警的方法

3.  编写一个抽象类Animal,抽象类中包括属性:name(String类型),抽象方法:speak().

  编写一个宠物接口Pet,接口中包括方法:eat()。

  再编写一个Cat,实现该接口和抽象类中的所有方法

在main中进行测试,输出:“miao,  my name is xxx”;  "I want to eat some fish"

public class AnimalTest2 {
public static void main(String[] args) {
Cat1 c = new Cat1("小黑");
c.speak();
c.eat();
     //此处也可用接口创建对象,但其只能调用接口中的方法(其他方法相当于子类中独有的方法,如speak)
     //Pet p = new Cat1("小黑");此叫接口的多态,同抽象类一样
//p.eat();

}
} abstract class Animal2{
String name;
abstract void speak();
} interface Pet{
void eat();
}
class Cat1 extends Animal2 implements Pet{
public Cat1(String name) {
this.name = name;
}
public void speak() {
System.out.print("my name is"+name);
}
public void eat() {
System.out.println(" I want to eat some fish");
}
}

4.

零基础学习java------day9------多态,抽象类,接口的更多相关文章

  1. 总结了零基础学习Java编程语言的几个基础知识要点

    很多Java编程初学者在刚接触Java语言程序的时候,不知道该学习掌握哪些必要的基础知识.本文总结了零基础学习Java编程语言的几个基础知识要点. 1先了解什么是Java的四个方面   初学者先弄清这 ...

  2. 音乐出身的妹纸,零基础学习JAVA靠谱么

    问:表示音乐出身的妹纸一枚  某一天突然觉得身边认识的是一群程序员   突然想 要不要也去试试... 众好友都觉得我该去做个老师,可是我怕我会误人子弟,祸害祖国下一代..... 要不要 要不要 学Ja ...

  3. “全栈2019”Java第一百零六章:匿名内部类与抽象类接口注意事项

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. 零基础学习hadoop到上手工作线路指导(编程篇)

    问题导读: 1.hadoop编程需要哪些基础? 2.hadoop编程需要注意哪些问题? 3.如何创建mapreduce程序及其包含几部分? 4.如何远程连接eclipse,可能会遇到什么问题? 5.如 ...

  5. 【零基础学习iOS开发】【转载】

    原文地址:http://www.cnblogs.com/mjios/archive/2013/04/24/3039357.html 本文目录 一.什么是iOS 二.主流手机操作系统 三.什么是iOS开 ...

  6. 李洪强iOS开发之【零基础学习iOS开发】【01-前言】01-开篇

    从今天开始,我就开始更新[零基础学习iOS开发]这个专题.不管你是否涉足过IT领域,也不管你是理科生还是文科生,只要你对iOS开发感兴趣,都可以来阅读此专题.我尽量以通俗易懂的语言,让每个人都能够看懂 ...

  7. 【零基础学习iOS开发】【01-前言】01-开篇

    本文目录 一.什么是iOS 二.主流手机操作系统 三.什么是iOS开发 四.学习iOS开发的目的 五.学习iOS开发的前提 从今天开始,我就开始更新[零基础学习iOS开发]这个专题.不管你是否涉足过I ...

  8. salesforce 零基础学习(六十八)http callout test class写法

    此篇可以参考: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restfu ...

  9. 零基础学习hadoop到上手工作线路指导(中级篇)

    此篇是在零基础学习hadoop到上手工作线路指导(初级篇)的基础,一个继续总结. 五一假期:在写点内容,也算是总结.上面我们会了基本的编程,我们需要对hadoop有一个更深的理解: hadoop分为h ...

随机推荐

  1. Luogu P1297 [国家集训队]单选错位 | 概率与期望

    题目链接 题解: 单独考虑每一道题目对答案的贡献. 设$g_i$表示gx在第$i$道题目的答案是否正确(1表示正确,0表示不正确),则$P(g_i=1)$表示gx在第$i$道题目的答案正确的概率. 我 ...

  2. 恶意代码の奇客pdf分析

    目录 恶意代码の奇客pdf分析 奇客PDF安装包分析 静态分析基础技术 上传杀毒网 查壳 编译时间 导入表分析 资源查看 动态分析基础技术 Process Monitor监控 Process Expl ...

  3. Vue2高级原理

    <div id="app">     <input type="text" v-model="username"> ...

  4. 你们不要再吵了! Java只有值传递..

    写在前边 上次聊到Java8新特性 lambda时,有小伙伴在评论区提及到了lambda对于局部变量的引用,补充着博客的时候,知识点一发散就有了这篇对于值传递还是引用传递的思考.关于这个问题为何会有如 ...

  5. httprunner3源码解读(2)models.py

    源码目录结构 我们首先来看下models.py的代码结构 我们可以看到这个模块中定义了12个属性和22个模型类,我们依次来看 属性源码分析 import os from enum import Enu ...

  6. ICMP 协议仿真及ping命令用途

    1.实验目的 加深对 IPv4 协议首部各定义域的理解,掌握路由表的结构和基本配置命令,熟悉 ICMP 的调试操作. 2.实验原理 IPv4 协议定义,网络层协议的相关 RFC 定义和描述. 3.实验 ...

  7. 攻防世界 WEB 高手进阶区 PHP2 Writeup

    攻防世界 WEB 高手进阶区 PHP2 Writeup 题目介绍 题目考点 url 二次解码 index.phps 文件(第一次使用dirsearch可能扫不到,需要加到工具字典里) php 简单语法 ...

  8. Spring中bean的初始化和销毁几种实现方式

    Bean的生命周期 : 创建bean对象 – 属性赋值 – 初始化方法调用前的操作 – 初始化方法 – 初始化方法调用后的操作 – --- 销毁前操作 – 销毁方法的调用. [1]init-metho ...

  9. CF285D.D. Permutation Sum

    CF285D. Permutation Sum 题目 大意 寻找a,b两个排列从0到n-1,有c[i]=(a[i]+b[i])%n+1,使得c[i]也为全排列的排列方式 思路 a中元素和b中元素的对应 ...

  10. 动手写一个简单的Web框架(模板渲染)

    动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...