文章目录
1.多态
1.1多态
1.1.1多态的概念
同:同一对象
不同:条件不同
同:对同一行为
不同:实现的结果不同
程序中:同一引用类型,由于实例不同,对同一方法产生的结果不同
1.1.2多态的实现
package com.chenlan03.poly1;
public class Test {
public static void main(String[] args) {
Pet pet = null;
pet = new Dog("lala", 90, 90, "拉布拉多犬");
pet.showInfo();
pet = new Penguin("heha", 80, 80, "Q仔");
pet.showInfo();
}
}
[1] 多态一定建立在继承的基础上
[2] 多态形式上表现为 父类对象调用子类实例
[3] 当父类引用子类时,通过父类调用方法一定是子类重写、实现的方法。
1.2多态的形式
1.2.1父类对象引用子类实例
1.2.2父类作为方法形参实现多态(运行时多态)
public void feed(Pet pet){
pet.eat();
}
package com.chenlan03.poly1;
public class Test {
public static void main(String[] args) {
Master master = new Master("chenchen");
Pet pet = null;
pet = new Dog("lala", 90, 90, "拉布拉多犬");
master.feed(pet);
pet.showInfo();
pet = new Penguin("heha", 80, 80, "Q仔");
master.feed(pet);
pet.showInfo();
}
}
父类作为方法形参,在编译期间,无法得知pet执行的是谁的eat()方法,只有当程序运行时,实参才传递给形参,此时我们才知道pet到底是什么具体的子类。
1.2.3父类作为返回值实现多态
1.3多态类型转换
1.3.1自动类型转换
父类可以自动转换为子类,称为向上类型转换
Pet pet = new Dog();
1.3.2强制类型转换
在多态中,父类引用子类时,无法调用子类独有的方法,所以要进行强制类型转换,称为向下类型转换
Pet pet = null;
Dog dog = (Dog) pet;
1.3.3instanceOf
用于判断一个运行时对象是否是指定的(父)类实例,返回boolean类型
package com.chenlan04.poly2;
public class Master {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Master() {
}
public Master(String name) {
this.name = name;
}
public Pet adopt(int type){
Pet pet = null;
switch (type) {
case 1:{
pet = new Dog();
break;
}
case 2:{
pet = new Penguin();
break;
}
}
return pet;
}
}
package com.chenlan04.poly2;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Master master = new Master("chenchen");
Scanner sc = new Scanner(System.in);
System.out.println("请选择要领养的宠物(1.狗狗 2.企鹅)");
int type = sc.nextInt();
Pet pet = master.adopt(type);
pet.setName("lala");
pet.setHealth(80);
pet.setLove(80);
if(pet instanceof Dog){
Dog dog = (Dog) pet;
dog.setStrain("拉布拉多犬");
}else if(pet instanceof Penguin){
Penguin penguin = (Penguin) pet;
penguin.setGender("Q仔");
}
pet.showInfo();
}
}
1.4多态总结
封装:保证类信息的安全性和正确性。
继承:减少重复性代码。
多态:提高程序的可拓展性、可维护性。
多态(Polymorphism)是面向对象编程语言的重要特性,它允许父类引用指向子类的对象,而在具体访问时实现方法的动态绑定。
多态的3个必要条件
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重写/实现,在调用这些方法时就会调用子类重写或实现方法。
向上转型(父引子):在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能执行子类的方法。
关于多态的理解:
在创建对象时,把左边的变量类型声明成它的父类,像Pet pet=new Dog()这样,左边是父类,右边是子类,左边表示编译类型,右边表示运行时类型,像这样编译类型和运行类型不同时,就出现多态!
因为编译时期找的是父类,所以如果父类中没有我们调用的方法,那编译就会失败,程序就无法执行,而如果父类中有方法,但是子类没有重写,那编译会通过,且会执行父类中的方法,因为运行时它会去子类中找,找不到,再去父类中找,所以就会执行父类中的方法了
1.6接口
接口是一种引用数据类型,使用关键字interface
package com.chenlan01.interface1;
public interface AInterface {
String name = "AInterface";
//推荐写法
public void print();
/*void print();*/
/*public abstract void print();*/
}
1.6.1接口的特性
【1】接口中可以定义属性,且默认是public static final类型
package com.chenlan01.interface1;
public class Test {
public static void main(String[] args) {
System.out.println(AInterface.name);
}
}
【2】接口中的方法都是public abstract方法
package com.chenlan01.interface1;
public class ImplClassA implements AInterface {
@Override
public void print() {
System.out.println("ImplClassA.print");
}
}
【3】接口不是类,不能被实例化,不能定义构造方法
【4】接口支持继承,且支持多继承,一个接口可以继承多个接口、
package com.chenlan01.interface1;
public interface CInterface extends AInterface,BInterface {
}
【5】一个类可以实现一个或多个接口。该类称为该接口的实现类、使用关键字implements,实现类必须实现接口中所有的抽象类方法。
package com.chenlan01.interface1;
public class ImplClassA implements AInterface {
@Override
public void print() {
System.out.println("ImplClassA.print");
}
}
【6】一个类可以继承一个父类实现多个接口,继承在前,实现在后
(要规避抽象父类与接口定义了相同的抽象方法,此时实现类实现的是父类的抽象方法)
package com.chenlan01.interface1;
public class ImplClassB extends ImplClassA implements BInterface {
@Override
public void showInfo() {
System.out.println("ImplClassB.showInfo");
}
}
接口规范了类的行为,拓展了类的行为
1.7接口的应用
1.7.1接口描述一种能力
接口描述的是一种能力,实现类必须实现接口中定义的能力,即实现类中具备了接口中定义的能力
1.7.2接口实现多态
接口可以实现多态。
【1】本质:接口 new 实现类实现多态
【2】多态的其他形式:接口作为方法形参,接口作为方法返回值
package com.chenlan03.interface3;
public interface DriverInterface {
public void drive();
}
package com.chenlan03.interface3;
public class Student implements DriverInterface {
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() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public void drive() {
System.out.println(this.name + "正在开车");
}
}
package com.chenlan03.interface3;
public class Teacher implements DriverInterface {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher() {
}
public Teacher(String name) {
this.name = name;
}
@Override
public void drive() {
System.out.println(this.name + "正在开车");
}
}
package com.chenlan03.interface3;
public class Test {
public static void main(String[] args) {
DriverInterface driverInterface = null;
driverInterface = new Student("chenchen",12);
driverInterface.drive();
driverInterface = new Teacher("linlin");
driverInterface.drive();
}
}
1.7.3接口是一种约定
接口是一种约定,约定了实现类应该具备的能力。
接口只关心实现类是否具备接口中定义的能力,而不关心实现类如何具备的这个能力
1.7.4面向接口编程
完成大型系统时,通过接口实现模块间的解耦,这种编程思维称为面向接口编程。
接口与抽象类的区别:
【1】都是引用类型,都不能被实例化
【2】它们都可以定义抽象方法,都可以实现多态。但是抽象类可以定义非抽象方法,而接口中定义的只能是抽象方法
【3】抽象类和接口都有传递性,但抽象类是单继承,而接口是多继承
【4】抽象类和子类解决的是模块内的问题,而接口解决的是模块间的问题
1.8内部类
【1】类之间的平行关系
一个文件可以有多个类,但只能有一个公共类,而且公共类的类名要与文件名一致
package com.chenlan05.inner1;
public class Test {
}
class Test01{
}
【2】类之间的包含关系
package com.chenlan05.inner1;
public class Outer {
public class inner{
}
}
1.8.1成员内部类
内部类Inner作为外部类的一个成员存在,Inner称为成员内部类
【1】创建成员内部类对象
package com.chenlan05.inner1;
import com.chenlan05.inner1.Outer.Inner;
public class Demo {
public static void main(String[] args) {
Outer outer = new Outer();
/*idea*/
/*Outer.inner inner = outer.new Inner();*/
Inner inner= outer.new Inner();
inner.showInfo();
}
}
【2】成员内部类特性
成员内部类可以直接访问外部类的私有成员
package com.chenlan05.inner1;
public class Outer {
private String name = "Outer";
public class Inner{
//规避内部类与外部类定义了同名变量的情况
String name = "Inner";
public void showInfo(){
System.out.println("inner.showInfo");
/*访问内部类的变量*/
System.out.println(name);
System.out.println(this.name);
/*访问外部类的变量*/
System.out.println(Outer.this.name);
}
}
}
1.8.2静态内部类
静态内部类作为外部类的一个静态成员成员存在,静态内部类不会随着外部类的加载而加载
【1】创建静态内部类对象
package com.chenlan06.inner2;
import com.chenlan06.inner2.Outer.Inner;
public class Test {
public static void main(String[] args) {
/*idea*/
/*Outer.Inner inner=new Outer.Inner();*/
Inner inner = new Outer.Inner();
inner.showInfo();
}
}
【2】静态内部类特性
静态内部类可以访问外部类的私有静态成员
package com.chenlan06.inner2;
public class Outer {
private static String name = "Outer";
static class Inner {
private static String name = "Inner";
void showInfo() {
System.out.println("Inner.showInfo");
System.out.println(name);
System.out.println(Inner.name);
System.out.println(Outer.name);
}
}
}
1.8.3方法内部类
当一个类存在于方法中时,构成方法内部类。方法内部类只能存在于方法中,同时也只能在方法中创建对象。
方法内部类前没有任何修饰符,因为内部类定义在方法中,都是局部存在的。
【1】创建方法内部类对象
方法内部类对象只可以在方法中创建
package com.chenlan07.inner3;
public class Outer {
public void print() {
int a = 10;
class Inner {
public void showInfo() {
System.out.println("Inner.showInfo");
/*方法内部类中访问了方法中的变量之后,jvm为变量加上了final关键字,变量不可修改*/
System.out.println(a);
/*方法内部类可以访问方法中的变量,但不能修改*/
/*a = 20;*/
}
}
/*a = 20;*/
Inner inner = new Inner();
inner.showInfo();
/*匿名对象*/
/*new Inner().showInfo();*/
}
}
【2】方法内部类特性
方法内部类可以访问方法定义的局部变量,但不可以修改。