一、继承
当多个类中存在相同的属性和行为时,将这些内容集中到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类就可以。提高了代码的复用性。
被继承的类称为父类,也称基类或超类;继承的类称为子类,也称为派生类。
1.语法规则
class (子类) extends (父类){
}
- Java中一个子类只能继承一个父类,即单继承;
- 子类会继承父类中所有 public 的字段和方法;
- 对于父类的 private 的字段和方法,子类可以继承但是无法访问;
- 子类的实例中,也包含这父类的实例,可以使用 super 关键字得到父类实例的引用
2.代码实例:
class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
class Cat extends Animal {
public Cat(String name) {
super(name); //调用父类的构造方法
}
}
class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly() {
System.out.println(this.name + "正在飞!");
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("小花");
cat.eat("食物");
Bird bird = new Bird("可可");
bird.fly();
}
}
3.super 使用方法:
- super ():调用父类的构造方法;
- super.data:调用父类的成员属性;
- super.func():调用父类的成员方法。
super 和 this 的区别
区别 | this | super | |
---|---|---|---|
1 | 概念 | 访问本类中的属性和方法 | 由子类访问父类中的属性、方法 |
2 | 查找范围 | 先查找本类,若本类没有就调用父类 | 直接调用父类 |
3 | 特殊 | 表示当前对象 | 无 |
4.继承方式支持多层继承,即子类可以进一步的再派生出新的子类,但一般不建议超过三层,例:
class A{
}
class B extends A{
}
class C extends B{
}
- protected 关键字
- 对于类的调用者来说,protected 修饰的字段和方法是不能访问的;
- 对于类的子类和同一个包的其他类来说,protected 修饰的字段和方法是可以访问的。
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
public class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly() {
System.out.println(this.name + "正在飞!"); //子类访问了父类的protected
}
}
扩展:
范围 | private | default | protected | public | |
---|---|---|---|---|---|
1 | 同一包中的同一类 | √ | √ | √ | √ |
2 | 同一包中的不同类 | √ | √ | √ | |
3 | 不同包中的子类 | √ | √ | ||
4 | 不同包中的非子类 | √ |
- final 关键字:功能是限制类被继承。
- final 修饰一个变量或者字段的时候,表示常量,不能更改。
- final 修饰类的时候,此时表示被修饰的类不能被继承
- final 修饰方法时为密封方法。
例:final 修饰变量
final int a = 10;
a = 20;//编译出错
二、组合
和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。
public class elephant{
}
public class giraffe{
}
public class zoo{
public elephant[] elephants;
public giraffe[] giraffes;
}
组合表示 has a 含义,上面的例子中,可以理解为动物园包含若干只大象和长颈鹿。
三、多态
对象在不同时刻表现出来的不同状态。多态可以让类的调用者对类的使用成本进一步降低。
1.向上转型
Bird bird = new Bird("可可");
Animal bird2 = bird;
Animal bird2 = new Bird("可可");
这两个代码表达是一个意思:bird2 是 Animal 的引用,指向Bird 的实例,这种写法称为向上转型。
2.动态绑定
发生的条件:
- 一定会发生向上转型;
- 父类和子类有重写方法;
- 通过父类的引用调用父类和子类同名的重写方法
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println("我是一只猪");
System.out.println(this.name + "正在吃" + food);
}
}
public class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void eat(String food) {
System.out.println("我是一只鸟");
System.out.println(this.name + "正在吃" + food);
}
}
public class Test {
public static void main(String[] args) {
Animal animal1 = new Animal("可可");
animal1.eat("饲料");
Animal animal2 = new Bird("花花");
animal2.eat("谷子");
}
}
此时, 我们发现:
- animal1 和 animal2 虽然都是 Animal 类型的引用, 但是 animal1 指向 Animal 类型的实例, animal2 指向Bird 类型的实例;
- 针对 animal1 和 animal2 分别调用 eat 方法, 发现 animal1.eat() 调用了父类的方法, 而animal2.eat() 调用了子类的方法。
四、方法重写
子类实现父类的同名方法,并且参数的类型和个数完全相同,此时情况为重写,也称为覆写、覆盖。可以使用@Override注解来显示指定重写
注意事项:
- 普通方法可以重写,static 修饰的静态方法不能重写;
- 重写中子类的方法的访问权限不能低于父类方法的访问权限;
- 只有在协变情况下,重写的方法返回值类型才和父类的方法不同。
- 重载的条件是方法名相同,参数个数和类型不同,返回值不做要求。重写和重载是完全不一样的。
多态的代码实例:
class Shape {
public void draw() {
}
}
class Cycle extends Shape {
@Override
public void draw() {
System.out.println("○");
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("□");
}
}
class Flower extends Shape {
@Override
public void draw() {
System.out.println("♣");
}
}
public class Test {
public static void main(String[] args) {
Shape shape1 = new Flower();
Shape shape2 = new Cycle();
Shape shape3 = new Rect();
drawMap(shape1);
drawMap(shape2);
drawMap(shape3);
}
public static void drawShape(Shape shape) {
shape.draw();
}
}