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. JAVA笔记1__基本数据类型/输入输出/随机数/数组

    /**八种基本数据类型 boolean byte short int long char float double */ public class test1{ public static void ...

  2. jmeter 数据库压力测试之MySql

    1.首先下载合适的数据库驱动:https://mvnrepository.com/artifact/mysql/mysql-connector-java 2.创建testplan,并添加jar包 3. ...

  3. SpringBoot目录文件结构总结(5)

    1.目录 src/main/java :存放java代码 src/main/resources static:存放静态文件,比如css.js.image(访问方式 http://localhost:8 ...

  4. charles抓包修改请求参数发送新的请求

    打开charles -->选择请求右击选择compose---修改参数发送请求

  5. InnoDB 索引详解

    1.什么是索引 索引是存储引擎用于快速找到记录的一种数据结构. 2.索引有哪些数据结构 顺序查找结构:这种查找效率很低,复杂度为O(n).大数据量的时候查询效率很低. 有序的数据排列:二分查找法又称折 ...

  6. [spojSUBLEX]Lexicographical Substring Search

    建立后缀自动机,对于同一个节点,出现次数是相同的(right的大小),同时满足单调性(长度越长出现次数越少),所以只需要考虑最长的串即可. PS:似乎也并不需要求依次后缀的max,不知道为什么-- 1 ...

  7. LRU缓存

    LRU缓存 struct Node{ int key; int value; Node* next; Node* pre; Node(): key(-1), value(-1), next(nullp ...

  8. Netty高性能网络应用框架对标P7面试题分享v4.1.70.Final

    概述 **本人博客网站 **IT小神 www.itxiaoshen.com 定义 Netty官网 https://netty.io/ 最新版本为4.1.70.Final Netty是一个异步的.事件驱 ...

  9. JavaScript Sanitizer API:原生WEB安全API出现啦

    10月18号, W3C中网络平台孵化器小组(Web Platform Incubator Community Group)公布了HTML Sanitizer API的规范草案.这份草案用来解决浏览器如 ...

  10. [CCC​2019] Tourism题解

    我们先考虑一下拿部分分: subtask1 考虑因为 \(n < 2k\) ,那么我们的划分一定是从中间某个地方裁开,且满足 \(k\) 的条件的,我们发现当划分点在 \([n\ mod\ k, ...