一、多态
1.定义--什么是多态?
a.同一个父类的不同子类对象,在做同一行为的时候,有不同的表现形式,这就是多态。
(总结为:一个父类下的不同子类,同一行为,不同表现形式。)
b."动态绑定":开发阶段,以父类做参数,以父类做返回值类型 (代码的通用性比较好);
程序运行时,会根据实际传入参数的类型,动态的调用该类型所对应的方法(扩展性好)。
c.多态的好处:提高代码的扩展性和可维护性。
【以父类做返回值】
【pizza父类】
package work.demo1;
public class Pizza {//父类--子类有培根披萨,海鲜披萨
//父类 1.声明共有属性 2.空参构造 有参构造 3.get set 方法 取值赋值 4.方法
String name;
int price;
int size;
public Pizza() {
}
public Pizza(String name, int price, int size) {
this.name = name;
this.price = price;
this.size = size;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void show() {//这个方法展示,所以子类共有的
System.out.println("名称"+name);
System.out.println("价格"+price);
System.out.println("尺寸"+size);
}
}
【Peigen子类】
package work.demo1;
import java.util.Scanner;
public class Peigen extends Pizza {//子类培根披萨
private int g;//培根披萨私有属性--克数
public Peigen() {//空参构造
}
public Peigen(String name, int price, int size, int g) {//有参构造
super(name, price, size);
this.g = g;
}
//get set
public int getG() {
return g;
}
public void setG(int g) {
this.g = g;
}
public void show() {
super.show();//引用父类方法
System.out.println("请输入培根克数:"+g);
}
}
【Haixian子类】
package work.demo1;
import java.util.Scanner;
public class Haixian extends Pizza {//子类海鲜披萨
private String food;//配料
public Haixian(String food) {
this.food = food;
}
public Haixian(String name, int price, int size, String food) {
super(name, price, size);
this.food = food;
}
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public void show() {
super.show();
System.out.println("输入配菜:"+food);
}
}
【dopizza工厂类】
package work.demo1;
import java.util.Scanner;
public class Dopizza {
public Pizza dopizza() {//方法签名 Pizza:返回类型,表示该方法返回一个 Pizza 对象
//父类做返回值的含义
//在 Java 中,父类作为返回类型是一种常见的设计模式,称为多态。
// 具体来说,当一个方法的返回类型是父类时,该方法可以返回任何继承自该父类的子类对象。
// 这种方式提供了更大的灵活性和扩展性。
//在代码中,dopizza 方法的返回类型是 Pizza,这是一个父类。
// 方法内部根据用户的输入创建了不同的子类对象(Peigen 和 Haixian),但最终返回的是一个 Pizza 类型的对象。
Pizza pizza = null;
//对象类型 对象名
System.out.println("请选择想要制作的比萨(1.培根比萨2.海鲜比萨):");
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
if(i==1){
System.out.println("请输入培根克数:");
int weight= sc.nextInt();
System.out.println("请输入比萨大小:");
int size = sc.nextInt();
System.out.println("请输入比萨价格:");
int price= sc.nextInt();
pizza=new Peigen("培根披萨",price,size,weight);
} else if (i==2) {
System.out.println("请输入配料信息:");
String food = sc.next();
System.out.println("请输入比萨大小:");
int size = sc.nextInt();
System.out.println("请输入比萨价格:");
int price= sc.nextInt();
pizza=new Haixian("海鲜披萨",price, size,food);
}
return pizza;
}
}
【Test测试类】
package work.demo1;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Dopizza dopizza =new Dopizza();
Pizza peigen = dopizza.dopizza();
peigen.show();
// 这段代码的功能是创建一个 Dopizza 对象,并调用其 dopizza 方法生成一个 Pizza 对象,然后调用 Pizza 对象的 show 方法显示披萨的信息。
// 创建 Dopizza 对象 dopizza。
// 调用 dopizza 对象的 dopizza 方法,返回一个 Pizza 对象 peigen。
// 调用 peigen 对象的 show 方法,显示披萨的信息。
}
}
【以父类做参数】
package work.demo1;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Dopizza {
public Pizza dopizza() {
Pizza pizza = null;
Scanner sc = new Scanner(System.in);
System.out.println("请选择想要制作的比萨(1.培根比萨2.海鲜比萨):");
int choice = readInt(sc, 1, 2);
if (choice == 1) {
System.out.println("请输入培根克数:");
int weight = readInt(sc, 0, Integer.MAX_VALUE);
System.out.println("请输入比萨大小:");
int size = readInt(sc, 0, Integer.MAX_VALUE);
System.out.println("请输入比萨价格:");
int price = readInt(sc, 0, Integer.MAX_VALUE);
pizza = new Peigen("培根披萨", price, size, weight);
} else if (choice == 2) {
System.out.println("请输入配料信息:");
String food = sc.next();
System.out.println("请输入比萨大小:");
int size = readInt(sc, 0, Integer.MAX_VALUE);
System.out.println("请输入比萨价格:");
int price = readInt(sc, 0, Integer.MAX_VALUE);
pizza = new Haixian("海鲜披萨", price, size, food);
}
return pizza;
}
// 父类 Pizza 作为参数传递的地方
public void processPizza(Pizza pizza) {
if (pizza instanceof Peigen) {
Peigen peigen = (Peigen) pizza;
System.out.println("培根披萨信息:");
peigen.show();
} else if (pizza instanceof Haixian) {
Haixian haixian = (Haixian) pizza;
System.out.println("海鲜披萨信息:");
haixian.show();
} else {
System.out.println("未知类型的披萨");
}
}
//异常处理
private int readInt(Scanner sc, int min, int max) {
while (true) {
try {
int value = sc.nextInt();
if (value >= min && value <= max) {
return value;
} else {
System.out.println("输入值不在有效范围内,请重新输入:");
}
} catch (InputMismatchException e) {
System.out.println("输入无效,请输入一个整数:");
sc.next(); // 清除错误输入
}
}
}
}
【Test测试类】
package work.demo1;
public class Test {
public static void main(String[] args) {
Dopizza dopizza = new Dopizza();
Pizza pizza = dopizza.dopizza();
dopizza.processPizza(pizza);
}
}
PS:父类做参数子类父类都一样,只有工厂类和测试类有修改,异常处理在下一篇笔记
这部分会修改,因为工厂设计模式就是父类做返回值。
2.使用多态的场景
程序中一定有两条业务线:
一条是继承线由父子类组成的;一条是关联线,两条线有业务关联,第二天业务线中,父类做参数了;父类做返回值类型了。
例如:动物园,饲养员喂养动物,猫狗猴子
3.表现形式与实现条件
(1)表现形式
a.父类做参数:扩展性做的很好。
b.父类做返回值类型(工厂设计模式):扩展性还不够好,反射的扩展性最好!
(2)实现条件:继承;重写;声明父类、new子类( Person stu =new Student();)。
父类 定义对象= new 子类();
4.多态中的类型转换
(1)向上类型转换(声明父类new子类):
将对象由子类类型 转成 父类类型(缩小范围了:为了程序代码的通用)。
只能调用继承父类的,或者重写父亲的资源;不能调用自己特有的。
(2)向下类型转换(子类类型,声明父类new子类):
可以调用子类特有的方法;为了防止类型转换错误,使用关键字instanceof
if(animal instanceof Cat){
((Cat) animal).play(); //向下类型转换:可以调用子类特有的资源了
}
5.声明父类new 子类
首先实现多态的条件:继承,重写,声明父类new 子类
声明父类new 子类是拼凑出来的
【👇声明父类】
public void feet(Animal animal){
animal.eat();
if(animal instanceof Cat){
((Cat) animal).play(); //向下类型转换:可以调用子类特有的资源了
}
}
【主方法里👇new 子类】
Cat cat=new Cat();
feeder.feet(cat);
二、设计模式
1.定义--什么时设计模式?
a.为了解决一类问题的,一种固定的功能代码。
b.一共有23种设计模式:
单例模式:构造方法私有化
工厂模式:父类做返回值类型
代理模式:多个实现类,实现同一个接口
2.简单工厂模式的基本要求
a.定义一个static方法,通过类名直接调用。
b.返回值类型是父类类型,返回的可以是其任意子类类型。
c.传入一个字符串类型的参数,工厂根据参数创建对应的子类产品。
三、抽象父类
1.抽象类的作用--为什么要学习抽象类?
因为父类没有创建对象的必要!所以就不让父类创建对象了,然后就父类为抽象的,抽象类就不能new 对象。
public abstract class Pizza { }
2.抽象类不能创建对象了,它还有必要拥有构造方法吗?--为了让子类调用!
四、抽象方法
1.定义--为什么要学习抽象方法?
为了告诉子类,必须重写该方法!
public abstract void show( );
总结 :A.一个类如果拥有抽象方法,那么这个类一定是抽象类;
但是一个类是抽象类,可以没有抽象方法。
B.以后再写父类,都要写成抽象的;
父类里,尽可能多的创建抽象方法。
五、fianl关键字:final 最终的,可以修饰属性.方法.类
1.final 类:不可以被继承。
2.final 方法:不可以被重写。
3.final 属性:基本类型:值不可以被改变。
引用类型:地址不可以被改变,对象属性可以变。
4.补充:
基本数据类型和引用数据类型的区别:基本类型传值,引用类型传地址