组合
组合也表示的是类之间的相互关系,不同于继承所表示的类之间的相互关系(is - a 关系),组合表示的类之间的相互关系是has - a 关系
如何理解is - a关系以及has - a 关系,is - a 关系就是类似 ”动物和猫“之间的关系,子类是猫,父类是动物,可以说猫就是动物,即 cat is a animal ,但是不能说 动物就是猫 ,这中说法不正确;简而言之,继承 的 is - a 关系指代的是子类继承父类。 而 has - a 可以简单理解为学校和 老师以及学生之间的关系,school has a teacher / school has a student 学校有老师/学校有学生 的包含的含义,同样不能写成 老师有学校/学生有学校这样是错误的,has - a 指代的是某个类具有另一个或多个类(注意这里,has - a 不是父子类的关系)
多态
本质上父类对象应用于子类的特征就是多态。
多态是一种编程思想,其具体的实现方式通过如下几个方法:
①向上转型
②动态绑定
③方法重写
向上转型
//父类
class Parents{
String LastName = "刘";
public parents(String LastName) {
this.LastName = LastName;
}
}
//子类
class Child extends Parents {
public child (String LastName) {
super(LastName);
}
}
//Test类
public static void main(String[] args) {
Child child = new Child("刘婵");
Parents par = child;//这一赋值过程就称为向上转型
}
向上转型:父类的引用(栈)指向子类对象(堆)
向上转型发生的时机:
①直接赋值(上述代码)
②方法传参
③方法返回
动态绑定
动态绑定是实际运行过程中,多数运行引用实际指向的对象中的方法
// Animal.java
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);
}
}
// Bird.java
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);
}
}
// Test.java
public class Test {
public static void main(String[] args) {
Animal animal2 = new Bird("乐乐");
animal2.eat("谷子");
}
}
// 执行结果
我是一只小鸟
乐乐正在吃谷子
可以从代码中看到,父类引用 = 子类对象,再调用两者都具有的方法的时候,调用的是子类的方法。这是因为,父类引用指向了子类的存储空间,子类这时候只继承了父类的所有属性和方法,但是自身也重写了一个eat方法、构造方法,空间占用就会比父类的对象的空间占用大(子类的空间一般比父类的大);这个时候引用指向的这个子类的空间,当调用方法的时候首先会在自身的新的空间中寻找,如果找不到则会到继承的空间中寻找。所以掉用了子类的方法。
方法重写
重写也称为覆写/覆盖(Override)
重写需要注意的事项:
①重写和重载完全两回事,切勿混淆
②普通的方法可以重写,static修饰的静态方法不能重写
③重写的子类的方法的访问权限不能低于父类的方法访问权限
④final修饰的方法不能被重写
⑤重写方法不能抛出新的异常检查,且异常检查不能比父类的异常检查更加宽泛
⑥重写方法必须方法名、参数列表相同,返回值类型应该小于等于父类的返回值类型
重写与重载的区别
①重载的方法名相同,但参数列表中的类型、个数或顺序不同;而重写的方法名、参数列表相同
②重载的范围一般限制在没有继承关系的一个类之中,或者具有继承关系的父子类中;而重写则只在继承关系的子类中
③重载没有权限方面的要求;重写要求子类的重写方法的访问权限不低于父类的访问权限
反射
在运行过程中,能够了解封装中的类的方法以及属性,以及调用对象的方法和属性,这种功能称为反射