多态
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/14
* @description
*/
public class Shape {
private int x;
private int y;
public Shape() {
}
public Shape(int x, int y) {
setX(x);
setY(y);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void show() {
System.out.println("横坐标 :" + getX() + ", 纵坐标 :" + getY());
}
}
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/14
* @description
*/
public class Rect extends Shape {
private int len;
private int wid;
public Rect() {
}
public Rect(int x, int y, int len, int wid) {
super(x, y);
setLen(len);
setWid(wid);
}
public int getLen() {
return len;
}
public void setLen(int len) {
if(len > 0)
this.len = len;
else
System.out.println("长度不合理!");
}
public int getWid() {
return wid;
}
public void setWid(int wid) {
if(wid > 0)
this.wid = wid;
else
System.out.println("宽度不合理哦!");
}
@Override
public void show() {
super.show();
System.out.println("长度是:" + getLen());
System.out.println("宽度是:" + getWid());
}
}
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/14
* @description
*/
public class ShapeRectTest {
public static void main(String[] args) {
Shape s1 = new Shape(17,2);
//当Rect类中没有重写show方法时,调用父类的show方法
//当Rect类重写show方法后,下面调用Shape类中show方法
s1.show();
System.out.println("=============================");
Rect r1 = new Rect(3,4,5,6);
//当Rect类中没有重写show方法时,调用父类的show方法
//当Rect类重写show方法后,下面调用Rect类中show方法
r1.show();
System.out.println("=============================");
Shape s2 = new Rect(8,8,9,9);
//当Rect类中没有重写show方法时,调用父类的show方法
//当Rect类重写show方法后,下面的代码在编译阶段调用Shape中的show方法, 在运行阶段调用Rect类中show方法
s2.show();
}
}
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/14
* @description
*/
public class ShapeRectTest {
public static void main(String[] args) {
Shape s1 = new Shape(17,2);
//当Rect类中没有重写show方法时,调用父类的show方法
//当Rect类重写show方法后,下面调用Shape类中show方法
s1.show();
System.out.println("=============================");
Rect r1 = new Rect(3,4,5,6);
//当Rect类中没有重写show方法时,调用父类的show方法
//当Rect类重写show方法后,下面调用Rect类中show方法
r1.show();
System.out.println("=============================");
Shape s2 = new Rect(8,8,9,9);
//当Rect类中没有重写show方法时,调用父类的show方法
//当Rect类重写show方法后,下面的代码在编译阶段调用Shape中的show方法, 在运行阶段调用Rect类中show方法
s2.show();
System.out.println("=============================");
//测试Shape类型的引用能否直接调用父类和子类独有的方法??
System.out.println("获取到的横坐标:" + s2.getX());
//s2.getLen(); Err:Shape类中找不到Rect中独有的方法
s2.show();
//调用静态方法
System.out.println("=============================");
s2.test(); //提示不建议使用引用.的方式访问
Shape.test(); //推荐使用
}
}
使用父类类型的引用调用子类独有方法的方式
子类 is-a 父类
- 子类转父类是小类型到大类型
- 自动类型转换 , 向上转型
- 父类转子类是大类型到小类型
- 强制类型转换, 显式类型的转换,. 向下转型
- 几个异常:
- ArithmeticException 异常 算术异常
- NumberFormatException: 数字格式异常
- ArrayIndexOutOfBoundsException: 数组下标越界异常
- NullPointerException: 空指针异常
- classCastException - 类型转换异常
抽象
抽象方法
抽象类
如果一个抽象类中没有抽象方法,抽象类中不能new对象原因是抽象类中包含抽象方法。不包含抽象方法的抽象类不是真正意义上的抽象类。
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/15
* @description
*/
public abstract class AbstractTest {
private int cnt;
public AbstractTest() {
}
public AbstractTest(int cnt) {
setCnt(cnt);
}
public int getCnt() {
return cnt;
}
public void setCnt(int cnt) {
this.cnt = cnt;
}
public abstract void show() ;
public static void main(String[] args) {
// AbstractTest at = new AbstractTest(); //抽象类不能实例化对象
// System.out.println("at.cnt=" + at.getCnt());
}
}
- 模板设计模式
- 多态的优点:
为了屏蔽不同子类的差异性,实现通用得编程
- 多态的**缺点: **
- 父类类型的引用不能直接访问子类独有的方法, 若调用则需要强转。
抽象类的应用
- 抽象方法不能为private
- 抽象方法不能为static
- 抽象方法不能为 final ```java package com.lagou.task09;
/**
- @author 西风月
- @date 2020/7/15
@description */ public abstract class AbstractAccount { //public final abstract class AbstractAccount { Err private double money; //Define abstract method public abstract double getLixi(); // public static abstract double getLixi(); Err // public final abstract double getLixi(); Error // private abstract double getLixi(); Error
public AbstractAccount() { }
public AbstractAccount(double money) {
this.money = money;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
} } ```
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/15
* @description
*/
public class FixedAccount extends AbstractAccount {
public FixedAccount(int i) {
super(i);
}
@Override
public double getLixi() {
return getMoney() * 0.03 * 1;
}
public static void main(String[] args) {
AbstractAccount aat = new FixedAccount(1000);
System.out.println("计算所得利息是:" + aat.getLixi());
}
}
接口
- 新特性 :从jdk1.9开始允许接口中出现私有方法
- 里面只能有常量
- public static final
- 里面只能有抽象方法(新特性除外), 注释中的关键字可以省略,但建议写上 ```java package com.lagou.task09;
/**
- @author 西风月
- @date 2020/7/15
- @description / public interface InterfaceTest { /public static final/ int CNT = 1; //里面只能有常量 //private void show() {}; //从jdk1.9开始允许接口中出现私有方法 /public abstract*/ void show(); //里面只能有抽象方法(新特性除外), 注释中的关键字可以省略,但建议写上 } ```
接口的实际意义:
- 实现多继承 ```java package com.lagou.task09;
/**
- @author 西风月
- @date 2020/7/15
- @description */
//使用implement关键字表达实现的关系,支持多实现 public class Gold implements Metal, Money { @Override public void shine() { System.out.println(“发出的金黄色的光芒!”); }
@Override
public void buy() {
System.out.println("买了好多好吃的~");
}
public static void main(String[] args) {
Metal mt = new Gold();
mt.shine();
// if(mt instanceof Gold) // ((Gold) mt).buy();
Money mn = new Gold();
mn.buy();
/* Money mn2 = new Money() {
@Override
public void buy() {
System.out.println("================");
}
};
mn2.buy();*/
}
}
```java
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/15
* @description
*/
public interface Metal {
//自定义抽象方法描述发光的行为
public abstract void shine();
}
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/15
* @description
*/
public interface Money {
public abstract void buy();
}
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/15
* @description
*/
public interface Runner {
public abstract void run();
}
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/15
* @description
*/
public interface Hunter extends Runner {
public abstract void hunt();
//增加一个抽象方法
//public abstract void show();
//将两个默认方法中的重复代码打包以供复用
private void show() {
System.out.println("在以后的开发中,尽量减少重复代码,也就是减少代码冗余!");
}
public default void show1() {
show();
System.out.println("show1()方法:这里仅仅时接口中的一个默认功能,子类可以按需选择是否重写");
}
public default void show2() {
show();
System.out.println("show2()方法:这里仅仅时接口中的一个默认功能,子类可以按需选择是否重写");
}
//增加静态方法 隶属于类层级, 也就是接口层级
public static void test() {
System.out.println("这里时静态方法,可以直接通过接口名.的方式访问,省略对象的创建");
}
}
package com.lagou.task09;
/**
* @author 西风月
* @date 2020/7/15
* @description
*/
public class Man implements Hunter {
@Override
public void hunt() {
System.out.println("出去打猎啦!");
}
@Override
public void run() {
System.out.println("我在追赶猎物!");
}
@Override
public void show1() {
System.out.println("为了给你几分薄面,就重写一下方法吧!");
}
public static void main(String[] args) {
Runner r1 = new Man();
r1.run();
Hunter h1 = new Man();
h1.hunt();
h1.run();
h1.show1();
Hunter.test();
//h1.test(); 静态接口方法调用非法
//应将接收方表达式替换为类型限定符 'com.lagou.task09.Hunter'
}
}
抽象类以及接口的区别
- abstract class / interface
- extends/implements
- 继承抽象类限制单继承, 接口可以多实现
- 抽象类中可以有构造方法,接口中不可以有构造
- 接口中类变量只能是常量,不能有成员变量
- 抽象类中可以有成员方法,接口中只能由抽象方法
- 抽象类增加方法子类可以不用重写,而接口中增加方法时实现需要重写(Java8以前的版本)
任务总结
- 多态(重中之重)
- 基本概念
- 语法格式:父类类型的引用指向子类的对象
- 多态的特点
- 类型转换
- 父子类? -> instanceof
- 向上转型
- 实际意义
- 屏蔽不同子类的差异性实现,通用的编程带来最终不同的效果。
- 抽象类(重点)
- 抽象方法
- abstract 没有方法体
- 抽象类
- 抽象类不能实例化对象
- 抽象类跟抽象方法的关系
- 真正意义上的抽象类需要有abstract关键字+abstract方法
- super() 调用抽象类的构造方法
- 实际意义: 继承, 强制性,规范 模板设计模式
- 建议使用抽象类的引用指向子类对象, 实现多态
- 抽象方法
- 接口
基本概念: interface implements
常量
抽象方法 (Java8以前)
多实现
接口跟类之间的关系
抽象类和接口的主要区别
Java8、java9: 允许出现非静态方法
增加私有方法 private