在 Java 中,继承(Inheritance)和实现(Implementation)是两个不同的概念,具有以下显著区别:
定义 | 继承是面向对象编程的一个核心特性,它允许一个类(子类)从另一个类(父类)获得属性和方法。通过继承,子类可以重用父类的代码,扩展父类的功能,或者对父类的方法进行重写。 |
目的 | 主要用于代码复用和扩展父类的功能。 |
语法 | 使用 extends 关键字来建立继承关系 |
访问权限 | 子类可以访问父类中除了 private 修饰的成员以外的其他成员 |
方法重写 | 子类可以重写父类的方法,以提供自己的实现 |
单继承限制 | Java 中一个类只能直接继承一个父类,不支持多继承,但可以通过多层继承来扩展功能 |
定义 | 实现是指一个类实现一个或多个接口 |
目的 | 用于定义类需要遵循的规范,强制类实现接口中定义的方法 |
语法 | 使用 implements 关键字来表明实现关系 |
访问权限 | 接口中的方法默认是 public 的,实现类中实现的方法也必须是 public 的 |
方法定义 | 实现类必须实现接口中定义的所有抽象方法,否则该类必须声明为抽象类(底部有介绍抽象类) |
多实现支持 | 一个类可以同时实现多个接口。 |
继承与实现的区别
特性 | 继承(Inheritance) | 实现(Implementation) |
---|---|---|
关系 | “是一个”(is-a) | “能做什么”(can-do) |
复用性 | 通过继承父类的属性和方法实现代码复用 | 通过实现接口提供的约定,实现多种行为 |
数量限制 | 一个类只能继承一个父类(单继承) | 一个类可以实现多个接口 |
强制性 | 子类可以选择重写父类方法,但不是强制性的 | 实现接口时必须提供所有接口方法的实现 |
层次结构 | 建立类的层次结构,表示类的继承关系 | 建立行为契约,表示类的行为能力 |
代码设计 | 适用于类之间有紧密关系的情况 | 适用于类之间有共同行为但无紧密关系的情况 |
继承示例
// 父类
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
// 子类
class Dog extends Animal {
// 重写父类的方法
@Override
void eat() {
System.out.println("This dog eats bones.");
}
void bark() {
System.out.println("This dog barks.");
}
}
public class InheritanceExample {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 输出 "This dog eats bones."
dog.bark(); // 输出 "This dog barks."
}
}
实现示例
// 定义接口
interface Animal {
void eat();
}
// 定义另一个接口
interface Pet {
void play();
}
// 实现类
class Dog implements Animal, Pet {
@Override
public void eat() {
System.out.println("This dog eats bones.");
}
@Override
public void play() {
System.out.println("This dog plays with its owner.");
}
}
public class ImplementationExample {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 输出 "This dog eats bones."
dog.play(); // 输出 "This dog plays with its owner."
}
}
继承和实现是Java中两种重要的机制,分别用于表示类之间的紧密关系和行为契约。继承强调类之间的“是一个”关系,通过继承父类的属性和方法实现代码复用,而实现则强调类的行为,通过实现接口定义的抽象方法来实现多种行为。
*抽象类
在 Java 中,抽象类是一种不能被实例化的类,它可以包含抽象方法和非抽象方法。
抽象类使用 abstract 关键字来声明。
抽象类的主要特点和用途包括:
- 包含抽象方法:抽象方法是只有方法签名,没有方法体的方法。这些方法必须在子类中被实现。
- 提供部分实现:抽象类可以为其子类提供一些公共的属性和部分方法的实现,子类可以继承并扩展这些实现。
- 定义通用行为:为一组相关的子类定义共同的行为和属性,明确子类应该具有的方法和特征。
- 强制子类实现特定方法:通过包含抽象方法,强制子类提供具体的实现,以确保子类具有特定的功能。
以下是一个抽象类的示例:
abstract class AbstractShape {
// 非抽象方法
public void displayInfo() {
System.out.println("This is a shape.");
}
// 抽象方法
public abstract double getArea();
}
class Circle extends AbstractShape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
在上述示例中,AbstractShape
是一个抽象类,包含了一个抽象方法 getArea
,子类 Circle
必须实现这个抽象方法。使用抽象类可以提高代码的可扩展性和可维护性,使得程序的结构更加清晰和合理。
抽象类和一般的父类的不同之处
- 抽象方法的存在:抽象类可以包含抽象方法,即只有方法声明而没有方法实现的方法。而一般的父类中的方法都有具体的实现。
- 实例化限制:抽象类不能被直接实例化,而一般的父类可以被实例化创建对象。
- 设计目的:抽象类更侧重于为子类定义共同的接口和部分实现,强调子类的共性和规范;一般父类可能更侧重于提供完整的功能实现,子类可以选择继承和复用。
抽象类的主要用途
- 定义标准和规范:为一组相关的类定义共同的方法和属性,明确子类必须实现的部分,保证代码的一致性和规范性。
- 部分实现共享:可以提供一些公共的、可复用的方法实现,减少子类的重复代码。
- 代码组织和架构:有助于构建清晰的类层次结构,使程序更具可读性和可维护性。
- 强调共性:突出一组类的共同特征和行为,让开发者更清晰地理解类之间的关系。
例如,在图形处理的程序中,可以定义一个抽象类 Shape
,包含抽象方法 calculateArea()
,然后不同的具体图形类如 Rectangle
、 Circle
等继承自 Shape
并实现 calculateArea()
方法,这样可以确保每个图形类都具有计算面积的能力,同时又能根据具体图形的特点进行不同的实现。