目录
什么是继承?
什么是父类?什么是子类?
继承有什么好处?
Java中的代码演示
构造方法在类继承中的作用
构造方法在继承关系中的使用
什么是多态?
方法的重载
重载代码演示
方法的覆盖
覆盖代码演示
向上转型和向下转型
向上转型
向上转型的代码演示
向上转型的优缺点
向下转型
向下转型的代码演示
多态的优点
什么是继承?
继承是面向对象编程中两个类之间的一种关系。被继承的类称为父类或超类,而继承父类的类则称为子类。
什么是父类?什么是子类?
父类实际上使所有子类公共域和公共方法的集合,而每个子类则是父类的特殊化,使对公共域和方法在功能、内涵方面的扩展和衍生。
继承有什么好处?
继承可以使代码结构更加清晰,降低编码和维护的成本。
Java中的代码演示
定义类的时候通过关键字extends指明要继承的直接父类。子类对象除了可以访问子类中直接定义的成员外,也可以访问父类的所有非私有成员。
class Animal { public String name; public int age; public void eat(){ System.out.println(name+"正在吃饭"); } } //子类 狗 class Dog extends Animal{ public void bark(){ System.out.println(name+"正在汪汪汪叫"); } } public class Test { public static void main(String[] args) { Dog d = new Dog(); d.eat(); //Dog类中并没有eat方法,eat方法是从Animal中继承而来的 d.bark(); System.out.println(d.name); } }构造方法在类继承中的作用
首先,构造方法不能被继承!因为子类对象要对继承的父类的成员进行初始化,所以,在创建子类对象时除了执行子类自己的构造方法,还需要执行父类的构造方法。
- 子类可以在自己构造方法使用关键字super来调用父类的构造方法,但是super调用的语句必须时子类构造方法第一条可执行语句
- 如果在子类定义构造方法中没有使用super来明确调用父类的构造方法,则在创建对象时,首先自动执行父类的无参构造方法,然后再执行自己定义的构造函数
会报错的情况
class Animal1{ public String name; //有一个参数的构造方法 public Animal1(String name){ this.name=name; } } class Cat extends Animal1{ //因为在子类的对象中没有使用super调用父类的有参构造方法,所以会报错 }不会报错的情况
class Animal1{ public String name; //有一个参数的构造方法 public Animal1(String name){ this.name=name; } } class Cat extends Animal1{ public Cat(String name) { super(name); //利用super 调用父类一个参数的构造方法 } }构造方法在继承关系中的使用
import java.awt.*; class Point { int x; int y; //有参构造方法 Point(int x,int y){ this.x=x; this.y=y; } //无参构造方法 复习前一节知识点!可以用this Point(){ this(0,0);//可以利用this调用上面一种构造方法 } @Override public String toString() { return "Point{" + "x=" + x + ", y=" + y + '}'; } } class Pixel extends Point { //子类中自己的成员变量 Color c; Pixel(int x,int y,Color c){ super(x,y); //一定要把super写在子类自己构造方法的内部 this.c=c; } @Override public String toString() { return super.toString()+" 颜色 "+c; } } public class Test3 { public static void main(String[] args) { Pixel p=new Pixel(3,24,Color.blue); System.out.println(p); } }输出结果
Point{x=3, y=24} 颜色 java.awt.Color[r=0,g=0,b=255]
【说明】上面的代码中,使用了俩次出现super的情况,一种是在构造方法中,另外一种在toString方法中,super可以表示当前对象的直接父类对象引用,通过super还以引用访问父类的属性和方法。什么是toString?https://baike.baidu.com/item/toString/9871895https://baike.baidu.com/item/toString/9871895【注意】使用this查找时首先在本类查找,在找不到时再到父类和祖先类中去寻找;使用super查找匹配方法时,首先到直接父类去寻找,如果在直接父类中找不到,则继续到其祖先类逐级往高层查找。
什么是祖先类?
Java中的祖先类是 Object类。它是所有类的根,无论是否显式继承,最终都会追溯到它
什么是多态?
多态性主要体现在以下两个方面。
- 方法的重载(overload)。也称参数多态,是指在同一个类中定义多个方法名相同,但是参数形态有所不同的方法【参数的个数不同,参数的位置不同,参数的类型不同】。一个类中可以有多个构造方法也叫做构造方法的多态性。
- 子类对父类方法的覆盖(override)。是因为继承带来的多态,子类中对父类的定义的方法重新定义,这样在子类中将覆盖来自父类的同形态方法。方法名、形参列表必须和父类保持一致,实现子类自己的逻辑
方法的重载
方法的重载就是在同一个类中存在多个方法名相同但是参数不同的方法。
方法调用的匹配处理的原则:首先就是按照“精确分配”原则去查找匹配方法,如果找不到则按“自动类型转换匹配”原则去查找能匹配的方法。
- 所谓“精确匹配”就是实参和形参类型完全一致。
- 所谓“自动类型转换匹配”是指虽然实参和形参不同,但是能将实参的数据按照自动原则赋值给形参。
重载代码演示
class A{ void test(int x){ System.out.println("test(int):"+x); } void test(long x){ System.out.println("test(long):"+x); } void test(double x){ System.out.println("test(double):"+x); } } public class Test4 { public static void main(String[] args) { A a1=new A(); a1.test(5); a1.test(10.0); } }输出结果显示
【说明】因为实参5默认是int型的数据,因此,有test(int x)方法存在时按照“精确匹配”原则处理,但如果无该方法存在,将按“转换匹配”原则处理,原则优先考虑匹配test(long x)方法。
【思考】如果将test(long x)和test (int)方法都注释掉,那么情况会怎么样?
答:会输出test(double)5.0和test (double) 10.0
方法的覆盖
子类将继承父类的非私有方法,在子类中也可以对父类定义的方法重新定义。这时将产生方法的覆盖。也就是通过子类对象访问的方法就是子类自己重新定义的方法。
【注意】子类在重新定义父类己有的方法时,应保持与父类完全相同的方法头部声明,也就是说,应该要与父类具有完全相同的方法名,参数列表,返回类型一般也要相同。
class B extends A{ //将覆盖父类的方法 void test(int x){ System.out.println("B:test(int):"+x); } //不会覆盖父类的方法 void test(int x,String y){ System.out.println("B:test(int,String):"+x+","+y); } }【注意】
- 方法名、参数列表完全相同时才会产生方法的覆盖。返回值类型,通常也要一致。
- 方法的覆盖不能改变方法的静态与非静态属性。子类中不能将父类的实例方法定义为静态方法,也不允许将父类的静态方法定义为实例方法。
- 不允许子类中方法的访问修饰符比父类的有更多的限制。
覆盖代码演示
class animal{ private int age; private String name; //生成构造函数 public animal(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void eat(){ System.out.println(this.getName()+"正在吃东西"); } } class dog extends animal{ public dog(int age, String name) { super(age, name); } @Override //对父类animal中的eat方法进行覆盖 public void eat() { System.out.println(this.getName()+"正在吃狗粮"); } } class cat extends animal{ public cat(int age, String name) { super(age, name); } @Override public void eat() { System.out.println(this.getName()+"正在吃猫粮"); } }向上转型和向下转型
向上转型
向上转型:实际上就是创建一个子类对象,将其当成父类的对象来使用
语法格式:父类类型 对象名 = new 子类类型();
向上转型有三种方法
- 直接赋值的向上转型
- 方法传参的向上转型
- 返回值向上转型
向上转型的代码演示
//父类 动物 class Animal { public String name; public int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat(){ System.out.println(name+"正在吃饭"); } } //子类 狗 class Dog extends Animal{ public Dog(String name, int age) { super(name, age); } public void bark(){ System.out.println(name+"正在汪汪汪叫"); } public void eat(){ System.out.println(this.name+"正在吃狗粮"); } } public class Test { public static void feed(Animal animal){ animal.eat(); } public static Animal getAnimal(){ return new Dog("旺财", 1); } public static void main(String[] args) { //1.直接赋值的向上转型 Animal animal= new Dog("旺财", 1); animal.eat(); //2.方法传参的向上转型 Dog dog=new Dog("旺财", 1); feed(dog); //3.返回值向上转型 Animal a=getAnimal(); a.eat(); } }输出三个旺财正在吃狗粮
向上转型的优缺点
向上转型的优点:让代码实现更简单灵活。向上转型的缺陷:不能调⽤到⼦类特有的⽅法。因为编译器之人父类中声明过的方法,子类独有的方法,父类中没有定义,编译器直接报错。
向下转型
向下转型:将父类引用再还原为子类对象。
向下转型的代码演示
class Animal { public String name; public int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat(){ System.out.println(name+"正在吃饭"); } } //子类 狗 class Dog extends Animal{ public Dog(String name, int age) { super(name, age); } public void bark(){ System.out.println(name+"正在汪汪汪叫"); } public void eat(){ System.out.println(this.name+"正在吃狗粮"); } } public class Test { public static void main(String[] args) { Animal a=new Dog("旺财",1); if(a instanceof Dog){ //如果a时Dog才会强转 Dog d=(Dog)a; d.bark(); } else{ System.out.println("不是Dog类型,不能被强转"); } }什么是Java在的instanceof
多态的优点
优点
- 能够降低代码的 "圈复杂度", 避免使⽤⼤量的 if - else
- 可扩展能⼒更强