• day12 面向对象(下)


    day12 面向对象(下) PQ

    一、三大特性之多态(polymorphism)

    1、多态的简介

    (1)概念

    ​ 单态:这个对象只有唯一的一种状态

    ​ Student s = new Student();

    ​ 多态:这个对象存在多种状态。 是指同一行为,具有多个不同表现形式。

    (2)多态实现的前提

    ​ 1)要有继承或者实现的关系

    ​ 2)方法的重写(如果没有方法重写,格式不会报错,这样的多态是没有任何意义)

    ​ 3)父类的引用指向子类对象(父new子)或者父接口的引用指向实现类对象(父接口new实现类)

    2、多态的体现

    (1)多态体现的格式

    父类类型 变量名 = new 子类对象();
    变量名.方法名();
    
    eg:
    Animal dog = new Dog();
    dog.eat();
    

    (2)多态思想下成员的特点

    1)实例变量

    ​ 对象被什么数据类型所修饰,这个变量就会调用谁的实例变量

    //父类:SuperClass
    public class SuperClass {
    	int num = 10;
    }
    
    //子类:SubClass
    public class SubClass extends SuperClass {
    	int num = 20;
    }
    
    //测试类:PolyDemo02
    public class PolyDemo02 {
    	public static void main(String[] args) {
    		//父new父
    		SuperClass superC = new SuperClass();
    		System.out.println(superC.num);//10
    		//子new子
    		SubClass subC = new SubClass();
    		System.out.println(subC.num);//20
    		System.out.println("===================");
    		//利用多态创建对象
    		SuperClass sc = new SubClass();
    		System.out.println(sc);//com.atguigu.poly.demo02.SubClass@15db9742 子类地址值
    		System.out.println(sc.num);//10
    	}
    }
    
    2)实例方法

    ​ 先看父类中是否有这个方法,如果有,执行子类重写后的方法;如果没有,编译报错

    //父类:SuperClass
    public class SuperClass {
    	public void method () {
    		System.out.println("父类的实例方法");
    	}
    }
    
    //子类:SubClass
    public class SubClass extends SuperClass {
    	public void method () {
    		System.out.println("子类重写后的实例方法");
    	}
    }
    
    //测试类:PolyDemo04
    public class PolyDemo04 {
    	public static void main(String[] args) {
    		//父new父
    		SuperClass superC = new SuperClass();
    		System.out.println(superC);  //com.atguigu.poly.demo04.SuperClass@15db9742
    		superC.method();//父类的实例方法
    		System.out.println("==============");
    		//子new子
    		SubClass subC = new SubClass();
    		System.out.println(subC);//com.atguigu.poly.demo04.SubClass@6d06d69c
    		subC.method();//父类的实例方法
    		System.out.println("==============");
    		//父new子
    		SuperClass sc = new SubClass();
    		System.out.println(sc);//com.atguigu.poly.demo04.SubClass@7852e922
    		sc.method();//父类的实例方法
    	}
    }
    
    3)构造器

    ​ 和原来一样

    //父类:SuperClass
    public class SuperClass {
    	
    	public SuperClass () {
    		System.out.println("父类的构造器");
    	}
    }
    
    //子类:SubClass
    public class SubClass extends SuperClass {
    	
    	public SubClass(){
    		//super(); 此处隐藏了JVM提供的super()
    		System.out.println("子类的构造器");
    	}
    }
    
    //测试类PolyDemo03
    public class PolyDemo03 {
    	public static void main(String[] args) {
    		//父new父
    		SuperClass superC = new SuperClass();//父类的构造器
    		System.out.println("================");
    		//子new子
    		SubClass subC = new SubClass();//父类的构造器      子类的构造器
    		System.out.println("================");
    		// 父new子
    		SuperClass sc = new SubClass();//父类的构造器      子类的构造器
    		System.out.println(sc);	//com.atguigu.poly.demo03.SubClass@15db9742	
    	}
    }
    

    3、多态的好处和弊端

    (1)多态的好处

    • 声明方法时,不再将形参写具体的引用数据类型,直接写父类的类型或者父类接口的类型
    • 对象数组的应用
    //Student类
    public class Student {
    	private String name;
    	private int age;
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
        //设置满参构造器
    	public Student(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    	//重写系统中自带的toString方法
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + "]";
    	}	
    }
    
    //测试类:PolyDemo05
    public class PolyDemo05 {
    	public static void main(String[] args) {
    		Student s1 = new Student("张三",18);
    		Student s2 = new Student("李四",23);
    		Student s3 = new Student("钱五",43);
    		Student s4 = new Student("孙六",23);
    		//对象数组
    		Student[] arr = {s1,s2,s3,s4};
    		
    		printArr(arr);
    	}
    	//object为顶级父类,将其放置形参
    	private static void printArr(Object[] arr) { 
    		for (int i = 0; i < arr.length; i++) {
    			Object obj = arr[i];
    			System.out.println(obj);
    		}
    	}
    }
    
    //运行结果
    Student [name=张三, age=18]
    Student [name=李四, age=23]
    Student [name=钱五, age=43]
    Student [name=孙六, age=23]
    

    (2)多态的弊端及解决办法

    1)多态的弊端

    ​ 在多态的情况下,对象无法调用自己的特有方法,只能调用子类改写父类的方法。

    2)多态的解决方法

    ​ 解决多态的弊端,引用数据类型的类型转换

    类型转换名称 类型转换方向
    向上转型(默认转换方式) 将子类的对象或者实现类的对象转换为父类的类型或者父接口类型(多态)
    向下转型(强制类型转换) 将父类类型或者父接口类型转换为子类类型或者实现类类型
    • 向下转型(强制类型转换)格式:
    子类类型   对象名 = (子类类型)父类类型的对象;
    eg:
    Animal cat = new Cat();  //多态
    Dog dog = (Dog)cat;      //强转
    
    • 引用数据类型强制类型转换时注意事项:

      可能会发生ClassCastException:类型转换异常

    3)instanceof关键字的引入

    ​ 强制转换时易发生类型转换异常,使用instanceof给引用变量做类型的校验

    • instanceof使用格式
    变量名 instanceof 数据类型 
    
    eg:
    c instanceof Cat
    
    • instanceof返回值

      instanceof为关系运算符,如果变量属于该数据类型,返回true;如果变量不属于该数据类型,返回false。

    4、练习题:猫狗

    1.定义动物类
    		属性:年龄,颜色
    		行为:eat(String something)方法(无具体行为,不同动物吃的方式和东西不一样,
    			something表示吃的东西)生成空参有参构造,set和get方法
    	2.定义狗类继承动物类	  
    		行为:eat(String something)方法,看家lookHome方法(无参数)
    	3.定义猫类继承动物类
    		行为:eat(String something)方法,逮老鼠catchMouse方法(无参数)
    	4.定义Person类
    		属性:姓名,年龄
    		行为:keepPet(Dog dog,String something)方法
    		功能:喂养宠物狗,something表示喂养的东西
    		行为:keepPet(Cat cat,String something)方法
    		功能:喂养宠物猫,something表示喂养的东西
    		实现以上两种行为,思考如何只写一个方法?
    		生成空参有参构造,set和get方法  	
    	5.测试以上方法
    	  使用多态、强转、instanceof等
    
    //Animal类
    public abstract class Animal {
    	private int age;
    	private String color;
        //设置set()、get()方法
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public String getColor() {
    		return color;
    	}
    	public void setColor(String color) {
    		this.color = color;
    	}
    	//设置无参构造器和满参构造器
    	public Animal(int age, String color) {
    		super();
    		this.age = age;
    		this.color = color;
    	}
    	public Animal() {
    		super();
    	}
    	//设置动物类的抽象方法
    	public abstract void eat(String something);
    }
    
    //Cat类 继承 Animal类
    public class Cat extends Animal{
    	//重写父类eat方法
    	public void eat(String something) {
    		System.out.println(getAge() + "岁" + getColor() + "色的小猫正在吃" + something);
    	}
    	//逮老鼠方法
    	public void catchMouse () {
    		System.out.println(getAge() + "岁" + getColor() + "色的小猫正在逮老鼠");
    	}
    	//设置构造器
    	public Cat() {
    		super();
    	}
    
    	public Cat(int age, String color) {
    		super(age, color);
    	}
    }
    
    //Dog类 继承 Animal类
    public class Dog extends Animal{
    	//重写父类抽象方法
    	@Override
    	public void eat(String something) {
    		System.out.println(getAge() + "岁" + getColor() + "色的小狗正在吃" + something);
    	}
    	
    	public void lookHome(){
    		System.out.println(getAge() + "岁" + getColor() + "色的小狗正在看家");
    	}
    	//设置构造器
    	public Dog() {
    		super();
    	}
    
    	public Dog(int age, String color) {
    		super(age, color);
    	}	
    }
    
    //Person类
    public class Person {
    	//喂养狗和喂养猫的方法为方法的重载,可以直接使用多态的好处一:声明方法时,不再将形参写具体的引用数据类型,直接写父类的类型或者父类接口的类型
    	/*// 喂养狗的方法
    	public void keepPet(Dog dog,String something) {
    		dog.eat(something);
    	}
    	
    	// 喂养猫的方法
    	public void keepPet(Cat cat,String something) {
    		cat.eat(something);
    	}*/
    	
    	public void keepPet (Animal a,String something) {
    		a.eat(something);
    	}
    }
    
    //测试类:
    public class PolyDemo06 {
    	public static void main(String[] args) {
    		//创建猫对象
    		Animal cat = new Cat(2,"白");
    		//创建狗的对象
    		Animal dog = new Dog(3,"黑");
    		//创建人对象
    		Person p = new Person();
    		// 调用饲养员的喂养猫的方法
    		p.keepPet(cat, "鱼");
    		
    		// 将多态形式的对象进行向下转型
    		if (cat instanceof Cat) {
    			Cat c = (Cat)cat;
    			c.catchMouse();
    		}
    		//cat对象不属于Dog,判断返回false
    		if (cat instanceof Dog) {
    			Dog d = (Dog)cat;
    			d.lookHome();
    		}
    		//Cat c = (Cat)dog;	
    		//c.catchMouse();
    		System.out.println("==================");
    		// 调用饲养员喂养狗的方法
    		p.keepPet(dog, "骨头");
    	}
    }
    

    二、匿名内部类

  • 相关阅读:
    Excel相关函数
    慢SQL优化
    idea 添加阿里代码检查插件
    Jmeter使用自定义编写代码
    七、一些困难的测试场景:多线程、持久化存储等
    六、测试驱动开发 TDD
    五、从宏观角度考虑单元测试
    四、使用Mock对象
    三、单元测试要测试的是什么? The Right-BICP
    二、优秀单元测试的五个特征FIRST
  • 原文地址:https://www.cnblogs.com/iris-/p/13399211.html
Copyright © 2020-2023  润新知