继承、组合、聚合的定义
继承、组合和聚合是面向对象编程中,用于实现类与类之间关系的三种常用机制。
继承(inheritance)是指一个类从另一个类中继承(inherit)其属性和方法,被继承的类被称作父类、基类或超类,继承的类被称作子类、派生类或衍生类。子类可以继承父类的所有属性和方法,也可以重写或添加自己的属性和方法,还可以继续被其他类继承。继承实现了“is-a”(是一个)的关系,即一个类是另一个类的特殊类型。例如,Animal类可以作为一个基类,而Fish类和Bird类可以分别继承Animal类,他们就都继承了Animal类的属性和方法,并且可根据自身的需要对这些属性和方法进行进一步扩展或重写。
组合(composition)是指一个类由其他类组成,这些类被称作成员变量或组成部分。通过组合,一个类可以实现更加复杂的功能,并且可以随时替换或改变其中的组成部分。组合实现了“has-a”(有一个)的关系,即一个类拥有其他类的对象。例如,一个汽车有发动机和轮胎等组件,这些组件就可以看作是汽车类的成员变量。
聚合(aggregation)是指一种整体与部分之间的关系,表示个体一般都可以脱离整体独立存在。在聚合中,一个类可以包含其他类的对象,但是被包含的对象也可以不属于该聚合对象。聚合是一种比组合更为弱关联、模糊的关系。例如,一个学校包含多个班级,班级是被聚合的对象,它们可以独立存在,即一个班级可以迁移到另一个学校。
java举例说明继承、组合、聚合的区别
下面是一个简单的Java代码示例,用于说明继承、组合和聚合的区别:
继承:
// 定义一个Animal基类
public class Animal {
private String name;
private int age;
// Animal类构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// Animal类方法
public void eat() {
System.out.println("Animal is eating.");
}
}
// 继承
public class Dog extends Animal {
private String barkSound;
// 继承Animal类的构造方法
public Dog(String name, int age, String barkSound) {
super(name, age);
this.barkSound = barkSound;
}
// 重写Animal类的方法
@Override
public void eat() {
System.out.println("Dog is eating.");
}
public void bark() {
System.out.println(barkSound);
}
}
// 组合
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void start() {
engine.start();
}
}
public class Engine {
public void start() {
System.out.println("Engine is starting.");
}
}
组合是一种部分和整体的关系,部分不能离开整体而单独存在,这里的Engine不能离开Car而存在,如果这个例子不太好理解,再举一个例子,公司和部门的关系,部门不能离开公司而单独存在
// 聚合
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Classroom {
private List<Student> students;
public Classroom(List<Student> students) {
this.students = students;
}
}
这里聚合也是一种部分和整体的关系,但部分可以离开整体而存在,比如Student可以离开CalssRoom而存在,在举一个例子,部门和员工的关系,员工可以离开部门而单独存在。
测试:
public class Test {
public static void main(String[] args) {
// 继承
Dog dog = new Dog("小黑", 2, "汪汪汪");
dog.eat();
dog.bark();
// 组合
Engine engine = new Engine();
Car car = new Car(engine);
car.start();
// 聚合
Student stu1 = new Student("小明", 18);
Student stu2 = new Student("小红", 19);
List<Student> students = new ArrayList<Student>();
students.add(stu1);
students.add(stu2);
Classroom classroom = new Classroom(students);
}
}
总结
下面是继承、组合和聚合的应用场景总结:
继承:继承常常用于实现“is-a”(是一个)的关系,例如Animal类作为基类,Dog类和Cat类作为其派生类,它们都是动物,因此继承了公共的属性和方法。另外,继承也提供了代码重用的机制,可以大幅减少程序代码量。
组合:组合常常用于实现“has-a”(有一个)的关系,例如汽车有发动机和轮胎等组件,这些组件可以看作是汽车类的成员变量。此外,通过组合的方式,可以灵活地组合不同的组件,实现更加灵活的对象构建。
聚合:聚合常用于实现整体与部分之间的关系,其关系较为松散,可以随时替换或改变其中的组成部分。例如,一个学校包含多个班级,班级是被聚合的对象,它们可以独立存在,即一个班级可以迁移到另一个学校。聚合的好处是可以在整体和部分之间建立一种“弱耦合”的关系,在保持整体完整性的同时允许部分的灵活变化。
需要注意的是,不同的应用场景对应不同的需求,因此应根据具体需求来选择实现方式。在实际开发中,可以根据以上总结,选择最适合的机制来实现类之间的关系,并且在设计时尽量符合面向对象编程的基本原则,例如单一职责原则、开放-封闭原则、里氏替换原则等。