面向对象编程——继承
- 继承定义:
- 目的:代码重用、类重用 (把多个类之间的共同的代码提取出来,放到父类中)
- 概念:父类/基类/超类 ; 子类/派生类(继承父类的类)
- 关键字:extends (扩展)
- 语法
代码示例:
//父类
public class Animal {
public String name;
public void eat(String food){
System.out.println(name + "正在吃" + food);
}
}
//子类 Cat 继承 Animal
public class Cat extends Animal {
public void jump(){
System.out.println(name + "正在跳");
}
}
//子类 Bird 继承 Animal
public class Bird extends Animal{
public void fly(){
System.out.println(name + "正在飞");
}
}
测试:
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
// name 和 eat 是从 Animal 中继承而来的
cat.name = "小花";
cat.eat("小鱼干");
// jump 是自己本身定义的
cat.jump();
// Bird 同理
Bird bird = new Bird();
bird.name = "吱吱";
bird.eat("野果");
// fly 是自己本身定义的
bird.fly();
}
}
结果:
注意:
- java中一个子类只能继承一个父类,即支持单继承;
- 子类会继承父类所有的public 的字段和方法;
- 对于父类的private 的字段和方法是无法访问的;
- 子类的实例中,也包含父类的实例,可以使用 super 关键字得到父类的实例引用
补充:
public | 可以在类外访问 |
private | 只能在类内部访问 |
protected | 可以被子类访问,也可以同包的其他类访问(在被同包的类访问的基础上,还能被其他包的子类访问) |
default | 包级权限,可以被同包的其他类访问 |
- 构造方法
- 每个类都有构造方法,如果不显式的创建构造方法,那么编译器就会默认生成一个构造方法;
- 当父类里面没有写构造方法的时候,就被自动生成了没有参数版本的构造方法;
- 此时如果直接 new 子类实例,就会调用到刚才父类这个没有参数版本的构造方法;
- 当父类例有构造方法的时候,并且这个构造方法带有参数的时候,编译器就不在自动生成五参数版本的构造方法;
- 此时在创建子类实例,就需要显式的调用父类的构造方法,并且进行传参,否则创建不出来父类的实例,就会编译出错;
- 修改这个问题的办法: 只要在子类的构造方法中显式调用父类的构造方法即可(使用super)。
示例:
倘若父类有带有参数的构造方法,若子类中无构造方法则会报错,即子类要在构造方法中显式调用父类的构造方法,使用super。
父类带有参数的构造方法:
子类报错:
修改后:
结论:
- 构造子类实例的时候,会在子类实例的内部自动构造一个父类的实例(子类实例中包含了父类实例,父类实例包含了父类的属性)
- 如果父类中有多重构造方法,这时候构造子类就需要显式的决定哪个构造方法
- final
使用 final 显式的禁止继承,防止继承被滥用。
同样拿上述Animal来举例:
给父类Animal 添加 final 关键字:
此时,子类 Bird 将不能继承父类 Animal:
ps:我们所使用的的String 字符串类,就是用 final 修饰的,不能被继承
面向对象编程——组合
- 组合(一个类的成员也可以是): 代码重用 ,也是面向对象的一个重要特性
- 组合表示的语义 has - a (拥有xxx ,包含 xxx)
- 继承表示的语义 is - a ( 是xxx )
代码示例:
public class School {
public SchoolMaster schoolMaster = new SchoolMaster();
public Student student1 = new Student();
public Student student2 = new Student();
public Student student3 = new Student();
public Student student4 = new Student();
public Student student5 = new Student();
public ClassRoom classRoom1 = new ClassRoom();
public ClassRoom classRoom2 = new ClassRoom();
}
由上述代码例子中,我们可以理解 has - a 语义: 一个学校“包含”若干个学生和教室,这里不能用继承,否则意思将变成 一个学校是学生/教室 ,这就是组合在设计类中的意义,即将一个类的实例作为另外一个类的字段。