面向对象---多态
这次是2021年01月19日的学习成果,总结于此,以便于之后的学习查漏补缺
目录
多态(重点)
多态概述
生活实例
实例1:
水果:苹果,香蕉,西瓜
实例2:
动物:老虎,狮子,大象
实例3:
动物叫:猫叫,牛叫,羊叫
总结:多态即为多种形态,状态
多态的实现条件
Java实现多态的必要条件:继承、重写。
当编译时类型和运行时类型不一致,就会出现多态(Polymorphism)
创建人的类(父类)
public class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
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 void eat() {
System.out.println("人吃饭");
}
public void sleep() {
System.out.println("人睡觉");
}
}
创建男孩类(子类)
public class Boy extends Person{
private String ID;
public Boy() {
super();
}
public Boy(String name, int age) {
super(name, age);
}
public Boy(String name, int age, String iD) {
super(name, age);
ID = iD;
}
public void play() {
System.out.println("男孩去打游戏");
}
@Override
public String getName() {
return super.getName();
}
@Override
public void setName(String name) {
super.setName(name);
}
@Override
public int getAge() {
return super.getAge();
}
@Override
public void setAge(int age) {
super.setAge(age);
}
@Override
public void eat() {
System.out.println("男孩在狼吞虎咽地吃饭");
}
@Override
public void sleep() {
System.out.println("男孩听着音乐睡觉");
}
}
创建女孩类(子类)
public class Girl extends Person{
private String number;
public Girl() {
super();
}
public Girl(String name, int age) {
super(name, age);
}
public Girl(String name, int age, String number) {
super(name, age);
this.number = number;
}
public void buy() {
System.out.println("女孩在买东西");
}
@Override
public String getName() {
return super.getName();
}
@Override
public void setName(String name) {
super.setName(name);
}
@Override
public int getAge() {
return super.getAge();
}
@Override
public void setAge(int age) {
super.setAge(age);
}
@Override
public void eat() {
System.out.println("女孩在斯文的吃饭");
}
@Override
public void sleep() {
System.out.println("女孩在安静地睡觉");
}
}
测试类
import java.awt.GridBagConstraints;
public class Test {
public static void main(String[] args) {
Person person1 = new Person();
person1.eat();
System.out.println("-------------");
Boy boy = new Boy("小明", 20);
boy.eat();
boy.sleep();
boy.play();
System.out.println("-------------");
Girl girl = new Girl();
girl.eat();
girl.sleep();
girl.buy();
System.out.println("-------------");
Person person2 = new Boy("李华",21);
person2.eat();
person2.sleep();
System.out.println("-------------");
Person person3 = new Girl();
person3.eat();
person3.sleep();
}
}
运行结果
多态实现基础
父类声明的变量可以引用所有子类的对象,这是多态实现的基础。
我们只有在 运行 的时候才会知道引用变量所指向的具体实例对象。
多态的作用
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。简单的说,就是用父类或接口的引用变量指向子类的对象。
多态的总结
在涉及多态的编程中,请注意以下细节:
1、静态方法
静态方法不能被重写,所以静态方法也没有多态性.
2、 成员变量
成员变量不具备多态性。成员变量的值取决于引用所属的类
3、成员方法
编译时:检查引用变量所属类中是否有所调用的方法。运行时:调用实际对象所属类中的重写方法。
多态的转型
在多变编程中涉及到引用数据类型之间的转换。
向上转型upcasting
向上转型就是子类转父类,这是由系统自动完成。
请注意:一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中特有的属性和方法
Person person2 = new Boy("李华",21);
person2.eat();
person2.sleep();
//The method play() is undefined for the type Person
//play这个方法没有为Person类定义
//person2.play();
System.out.println("-------------");
Person person3 = new Girl();
person3.eat();
person3.sleep();
//The method buy() is undefined for the type Person
//buy这个方法没有为Person类定义
//person3.buy();
那么,怎么解决,子类转为父类无法调用自己的方法,这个问题呢,使用先下面的强制类型转换符 ()
向下转型downcasting
向下转型就是父类转子类,此时需要使用强制类型转换符 ()
Person person2 = new Boy("李华",21);
//父类对象强转为子类对象
Boy boy1 = (Boy) person2;
boy1.eat();
boy1.sleep();
//The method play() is undefined for the type Person
boy1.play();
System.out.println("-------------");
Person person3 = new Girl();
//父类对象强转为子类对象
Girl girl1 = (Girl)person3;
girl1.eat();
girl1.sleep();
//The method buy() is undefined for the type Person
girl1.buy();
运行结果:
转型实例:
//父类引用指向子类对象
Person person4 = new Boy();
person4.eat();
//Error code
//person4.play();
类型转换的重点:
1、弄清楚继承关系、谁是父类谁是子类
2、关键点在于创建对象时调用的是谁的构造函数
多态与instanceof
在多态编程中可以通过instanceof判断对象到底属于哪个确切的类型
boolean result = boy instanceof Boy;
System.out.println(result);
result = person1 instanceof Person;
System.out.println(result);
运行结果:
运用if语句判断,避免 子类转为父类无法调用自己的方法
Person person2 = new Boy("李华",21);
if(person2 instanceof Boy) {
((Boy) person2).play();
}
多态的应用场景
基于继承的多态
多个子类对同一方法的重写,可以在运行时表现出不同的行为
基于接口的多态
一个接口可以有多 个实现类。所以,多个实现类对接口中同一方法的重写,可以在运行时表现出不同的行为。
场景: 接口名 变量名 = new 类名()
MyClass myClass = new MyClass();
MyInterface myInterface = new MyClass();
注意:命名规范,接口名 —> 接口名Impl
public class MyInterfaceImpl implements MyInterface {
}
函数输入参数的多态
多态可以作为形参,接受范围更广的对象,接受的参数更加灵活
public static void main(String[] args) {
Person person5 = new Person();
test1(person5);
}
public static void test1(Person person5) {
if(person5 instanceof Boy) {
((Boy) person5).Play();
}
if(person5 instanceof Girl) {
((Girl) person5).buy();
}
}
public static void main(String[] args) {
MyInterface myInterface = new MyInterfaceImpl();
test2(myInterface);
}
public static void test2(MyInterface myInterface) {
}
函数返回值的多态
多态可以作为返回值,接受范围更广的对象
public 父类 方法名(){
return 父类对象;
return 子类对象;
}
public static Person test1() {
Person person = new Person();
Boy boy = new Boy();
Girl girl = new Girl();
return girl;
}
public static MyInterface test3() {
MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl();
return myInterfaceImpl;
}
public static Fruit test4() {
return new Apple;
}
内部类
1、概述
在一个类的内部定义的类称为内部类,其实就是类定义的位置发生了变化。在类中定义的内部类叫成员内部类,在函数中定义的内部类叫局部内部类,使用static 修饰的成员内部类叫静态内部类。静态内部类使用很少,用的最多的是成员内部类。
注意:内部类生产的class文件为 “ 外部类$内部类 ”, 它表明该内部类是属于哪个外部类的。
2、成员内部类
(1)定义成员内部类
1、成员内部类也是一个类,可以有自己的成员属性、成员方法。
2、成员内部类可以访问外部类的成员方法和成员属性。
3、在内部类中,this.name中的this表示内部类
小结
内部类访问外部类的字段:外部类类名.this.字段
内部类访问外部类的方法:外部类类名.this.方法.
内部类访问内部类字段: this.字段
内部类访问内部类方法: this.方法
//外部类
public class Forest {
private int treeType;
public int getTreeType() {
return treeType;
}
public void setTreeType(int treeType) {
this.treeType = treeType;
}
public static void printTree() {
System.out.println("好树!好树啊!");
}
//内部类
class Animal{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTreeType() {
//访问外部属性
int type = Forest.this.getTreeType();
return type;
}
}
}
(2)成员内部类的使用
成员内部类必须依赖于外部类的对象。
所以,首先创建外部类,然后使用外部类的实例创建普通内部类。
示例如下:
第一种写法:
//创建外部对象
Forest forest = new Forest();
//创建内部类对象
Forest.Animal animal = forest.new Animal();
//内部类对象调用方法
int number = animal.getTreeType();
System.out.println(number);
第二种写法:
Forest.Animal animal = new Forest().new Animal();
int number = animal.getTreeType();
System.out.println(number);
小结:
内部类的访问特点:
1、内部类可以直接访问外部类的成员,包括外部类的私有对象。
2、外部类要访问内部类的成员,必须创建对象。
5、匿名对象(掌握)
1、没有名字
2、仅能使用一次
//匿名对象,直接调用方法,只能用一次
new Forest().printTree();
6、匿名内部类(掌握)
匿名内部类是-种特殊的内部类,它在语句内部定义,没有类名。例如:在GUI程序中作为事件处理函数。
匿名内部类必须继承-个父类或者是实现一个接口。语法格式:
new 父类或者接口(){
执行代码...
};
每次创建匿名内部类的对象时,必须先定义匿名内部类,然后马上使用new创建对象。如果希望再次创建这个匿名内部类的对象,必须重定定义匿名内部类,即每个匿名内部类的定义只能使用一次。
定义接口:
public interface MyInterface1 {
void sayHello();
}
public class MyInterface1Impl implements MyInterface1{
@Override
public void sayHello() {
System.out.println("Hello 好好学习");
}
}
测试程序:
public class Test1 {
public static void main(String[] args) {
Test1 demo = new Test1();
MyInterface1Impl myInterface1Impl = new MyInterface1Impl();
myInterface1Impl.sayHello();
demo.test(myInterface1Impl);
System.out.println("---------");
// 下面括号里new开始到});就是一个对象
demo.test(new MyInterface1() {
@Override
public void sayHello() {
System.out.println("大家好");
}
});
}
public void test(MyInterface1 myinterface1) {
myinterface1.sayHello();
}
}
运行结果:
本文地址:https://blog.csdn.net/qq_49290616/article/details/114187401