java零基础入门学习第八天——相关笔记
多态
多态:多种状态,同一对象在不同情况下表现出不同的状态或行为
Java中实现多态的步骤:
1.要有继承(或实现)关系
2.要有方法重写
3.父类引用指向子类对象(is a关系)
package study3.demo;
//Animal类的子类
public class Dog extends Animal {
//因为狗吃骨头,所以优化父类的eat()方法
@Override //方法重写的关键字;有方法重写时建议写上
public void eat() {
// getName()通过这个调用父类的name,父类用private修饰了
System.out.println(getName()+"吃骨头");
}
}
package study3.demo;
//定义父类
public class Animal {
// 姓名
private String name;
//空参
public Animal() {
}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void eat() {
System.out.println("吃东西");
}
}
package study3.demo;
/*
动物类案例:
已知父类Animal,成员变量为:姓名,成员方法为:eat()方法
其有一子类Dog类,请用该案例摸你多态
*/
public class Test4 {
public static void main(String[] args) {
//需求“演示多态
/*
Java中实现多态的是哪个步骤:
1.要有继承(或实现)关系
2.要有方法重写
3.要有父类引用指向子类对象
*/
// 多态:狗是一个动物
Animal a = new Dog(); //父类引用指向子类对象
// 测试成员方法的调用
// 结论:多态中调用成员方法是
// 编译看左(左边的类型(父类:Animal)有没有这个成员)
// 运行看右(运行时具体用的是右边类(子类:Dog)中的该成员)
a.setName("哈士奇");
//
a.eat();
}
}
结论:多态中调用成员方法是
编译看左(左边的类型(父类)有没有这个成员)
运行看右(运行时具体用的是右边类(子类)中的该成员)
多态效果演示
需求:父类型变量作为参数时,可以接受任意子类对象
package study3.demo;
public class Dog2 extends Animal2 {
@Override
public void eat() {
System.out.println(getName()+"吃骨头");
}
}
package study3.demo;
public class Mouse extends Animal2 {
@Override
public void eat() {
System.out.println(getName()+"吃奶酪");
}
}
package study3.demo;
//Animal类父类
public class Animal2 {
private String name;
public Animal2() {
}
public Animal2(String name) {
this.name = name;
}
//因为成员变量时私有的,所以要有setXxx()和getXxx()方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 成员方法
public void eat() {
System.out.println("吃饭");
}
}
package study3.demo;
/*
已知父类Animal,成员变量为:姓名,成员方法为:eat()方法
它有两个子类Dog类,Mouse类,两个子类都重写了Animal类中的eat()方法
在测试类中,定义showAnimal()方法,用来测试Dog类和Mouse类
*/
public class Test5 {
public static void main(String[] args) {
//用来测试Dog类和Mouse类
// 测试Dog类
Dog2 d = new Dog2();
d.setName("小A");
showAnimal(d);
// 测试Mouse类
Mouse m = new Mouse();
m.setName("小B");
// m.eat();
showAnimal(m);
}
// 需求:在该类中定义showAnimal()方法
// 传统做法
// 因为是在测试类中的,所以要加static
// public static void showAnimal(Dog2 d) {
// d.eat();
// }
// public static void showAnimal(Mouse m) {
// m.eat();
// }
// 多态的做法
// 多态的使用场景:
// 父类型可以作为形参的数据类型,这样可以接受其任意的子类对象
public static void showAnimal(Animal2 a) {
a.eat();
}
}
多态的使用场景:父类型可以作为形参的数据类型,这样可以接受其任意的子类对象
多态关系中成员变量的使用
需求:子父类中定义了同名的成员变量,如何调用
package study3.demo;
public class Animal3 {
String name = "小A";
}
package study3.demo;
public class Dog3 extends Animal3 {
String name = "小B";
}
package study3.demo;
/*
结论:多态关系中,成员变量是不涉及到重写的
简答记忆:多态关系中,使用成员变量,遵循“编译看左,运行看左”
编译看左:在编译期间会看左边的类型有没有这个成员,没有就报错,有就不报错
运行看左:在运行期间使用的是左边的类型中的这个成员
*/
public class Test6 {
public static void main(String[] args) {
// 通过多态的方式创建对象,然后测试成员变量的使用
// 多态:父类引用指向子类对象
Animal3 a = new Dog3();
System.out.println(a.name);
// 通过普通方式创建对象,然后测试
Dog3 d = new Dog3();
System.out.println(d.name);
}
}
结论:多态关系中,成员变量是不涉及到重写的(成员变量不能重写)
简答记忆:多态关系中,使用成员变量,遵循“编译看左,运行看左”
编译看左:在编译期间会看左边的类型有没有这个成员,没有就报错,有就不报错
运行看左:在运行期间使用的是左边的类型中的这个成员
多态的好处:
**1.可维护性:**基于计划才能关系,只需要维护父类代码,提高了代码的复用性,大大降低了维护程序的工作量
**2.可扩展性:**把不同的子类对象都当做父类看待,屏蔽了不同子类对象间的差异,做出通用的代码,以适应不同的需求,实现了向后兼容
多态的缺点:
不能使用子类特有成员
类型转换:当需要使用子类特有功能时,需要进行类型转换
向上转型(自动类型转换):子类型转换成父类型
如:将Dog()类型的转成Animal类型的
Animal a = new Dog();
向下转型(强制类型转换):父类型转换成子类型
如:将Animal类型的animal转成Dog类型,小括号里面写要转成的类型
Dog d = (Dog) animal;
注意事项:
1.只能在继承层次内进行转换(ClassCastException)
2.将父类对象咋混换成子类对象之前,使用instanceof进行检查
package study3.demo;
public class Animal4 {
public void eat() {
System.out.println("吃饭");
}
}
package study3.demo;
public class Dog4 extends Animal4 {
public void eat() {
System.out.println("狗吃骨头");
}
// 狗类独有的方法,父类中是没有这个成员方法的
public void whtch() {
System.out.println("狗会看家");
}
}
package study3.demo;
//子类,
public class Cat extends Animal4 {
}
package study3.demo;
/*
需求:
多态的好处:1.可维护性;2.可扩展性
多态的弊端:父类引用不能使用子类的特有成员
解决方案:通过“类型转换”实现
注意:只能在继承层次内进行转换,否则会报ClassCastException异常
将父类对象转换成子类之前,使用instanceof进行检查
instanceof关键字的用法:
对象名 instanceof 数据类型
意思是判断前边的对象是否是后边的数据类型
*/
public class Test7 {
public static void main(String[] args) {
// 需求:通过多态创建对象,调用子类中的成员
// Animal4 a = new Animal4();
Animal4 a = new Dog4();
// 调用eat()方法
a.eat();
// 调用watch()方法,属于子类独有的方法
// a.watch(); //报错
// 正确的写法
// Dog4 d = (Dog4) a;
// d.whtch();
// 不正常的转换 ClassCastException
// Cat c =(Cat)a;
// 优化后的方法:判断当前对象是否Dog类的对象,如果是,再调用watch()方法
if (a instanceof Dog4) { //判断是否是Dog类的对象
// 能走到这里,说明条件满足
Dog4 d = (Dog4)a;
d.whtch();
}
}
}
上一篇: C++结构体的各种用法
下一篇: java零基础入门学习第八天——相关笔记