前言:在生活中,我们常会羡慕身边的“高手”。比如羽毛球高手轻松接下别人的杀手锏,乒乓球高手胶着情况下“神来之笔”打出妙球。这都是因为高手具备我们没有的技能。那么,在Java世界,我们的类也可以通过“继承”这种手段来解锁新的能力,成为一个高手类。
继承的定义
首先,让我们从继承的定义开始吧。继承是一种能力,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。这意味着子类可以使用父类的方法和属性,同时还可以添加自己的方法和属性。这种 is-a 关系,帮助子类拥有父类的 “能力”。
那么,为什么要使用继承呢?这其实很简单,使用继承可以帮助我们减少代码的重复,提高代码的可复用性。如果我们需要创建一个新的类,它和现有的类有很多相同的属性和方法,那么我们可以继承现有的类,从而避免重复编写相同的代码。
接下来,让我们来看一下Java中的继承是如何工作的。在Java中,我们使用关键字“extends”来实现继承。
public class ChildClass extends ParentClass {
// ...
}
下面是一个继承的例子:
public class Animal {
public void eat() {
System.out.println("Animal is eating");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking");
}
}
在这个例子中,我们创建了一个Animal类和一个Dog类。Dog类继承了Animal类,因此它可以使用Animal类中的方法。在Dog类中,我们还添加了一个新的方法bark()。
现在,我们可以创建一个实例来测试一下这个例子:
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 输出 "Animal is eating"
dog.bark(); // 输出 "Dog is barking"
}
}
在这个例子中,我们创建了一个Dog对象,并调用了它的eat()和bark()方法。由于Dog类继承了Animal类,因此它可以使用Animal类中的eat()方法。
继承的特性
子类访问父类
首先,子类可以访问父类的所有非私有属性和方法。这包括父类的公有属性和方法、受保护的属性和方法以及默认属性和方法(即没有访问修饰符的属性和方法)。但是,子类不能访问父类的私有属性和方法。
举个例子,假设我们有一个父类叫做Vehicle,其中包含了一些属性和方法:
public class Vehicle {
public String brand;
protected int maxSpeed;
private int price;
public void run() {
System.out.println("Vehicle is running");
}
protected void stop() {
System.out.println("Vehicle is stopping");
}
private void startEngine() {
System.out.println("Engine is starting");
}
}
在这个例子中,Vehicle类包含了三个属性:brand、maxSpeed和price。它还包含了三个方法:run()、stop()和startEngine()。其中,run()和stop()方法是公有的,而startEngine()方法是私有的。
然后我们可以创建一个子类Car,它继承了Vehicle类:
public class Car extends Vehicle {
public String color;
public void drive() {
System.out.println("Car is driving");
}
}
在这个例子中,Car类继承了Vehicle类,并且添加了一个新的属性color和一个新的方法drive()。
由于Car类继承了Vehicle类,因此它可以访问Vehicle类中的所有非私有属性和方法。这包括brand、maxSpeed、run()和stop()方法。因此,我们可以在Car类中使用这些属性和方法:
public class Test {
public static void main(String[] args) {
Car car = new Car();
car.brand = "Toyota";
car.maxSpeed = 200;
car.run();
car.stop();
car.drive();
}
}
子类重写父类
此外,子类还可以重写父类的方法,也就是说,在子类中定义一个和父类中同名的方法。当子类调用这个方法时,它会覆盖父类中的方法。这种行为称为方法重写。
假设我们有一个父类叫做Animal,其中包含了一个方法eat():
public class Animal {
public void eat() {
System.out.println("Animal is eating");
}
}
现在,我们可以创建一个子类Dog,它继承了Animal类,并且重写了eat()方法:
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("Dog is eating");
}
}
在这个例子中,Dog类继承了Animal类,并且使用@Override注解重写了eat()方法。这意味着,当我们在Dog类中调用eat()方法时,它会覆盖父类Animal中的eat()方法,并输出“Dog is eating”。
下面是一个测试代码:
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.eat(); // 输出 "Animal is eating"
Dog dog = new Dog();
dog.eat(); // 输出 "Dog is eating"
}
}
在这个测试代码中,我们分别创建了一个Animal对象和一个Dog对象,并调用它们的eat()方法。由于Dog类重写了eat()方法,因此当我们调用Dog对象的eat()方法时,它会输出“Dog is eating”,而不是Animal类中的“Animal is eating”。
调用构造函数
最后,子类可以调用父类的构造函数。我们可以使用关键字“super”来调用父类的构造函数。这通常在子类中定义自己的构造函数时使用。
public class Animal {
public Animal(int age) {
this.age = age;
}
}
public class Dog extends Animal {
public Dog(int age) {
super(age);
}
}
在这个例子中,我们定义了两个构造函数,一个在Animal类中,另一个在Dog类中。在Dog类的构造函数中,我们使用关键字“super”来调用Animal类的构造函数,从而设置age属性。
有趣的细节
好了,现在我们已经了解了Java中继承的一些基本概念和特性,接下来我们来看一些有趣的细节。
你知道吗?在Java中,一个类只能继承一个父类,这被称为单一继承。这是因为Java中不允许菱形继承,也就是说,如果一个类有两个父类,并且这两个父类都有一个相同的方法,那么编译器将无法确定应该使用哪个方法。
但是,Java中的接口可以多继承。这是因为接口中只有方法的声明,而没有方法的实现。因此,在多个接口中声明相同的方法不会造成冲突。
另外,你知道吗?在Java中,所有的类都继承自Object类。这是因为Object类是Java中所有类的根类,它包含了一些通用的方法,比如toString()方法和equals()方法。因此,即使我们没有显式地继承Object类,我们的类仍然会默认继承它。
继承的好处:
想必经过上面的介绍,一定可以理清为什么要使用继承了吧!它主要有以下的优点:
- 重用代码:子类可以复用父类的属性和方法,无需重复编写。
- 扩展功能:子类在继承父类的同时,可以添加新的属性和方法,扩展其功能。
- 类型兼容:子类是父类的一种类型,这种类型兼容性帮助方法的重载选择。
- 多态:继承是实现多态的基础,让子类对象可以当成父类对象使用。
继承的缺点:
当然继承机制也有其缺点
- 耦合性高:子类高度依赖父类,一旦父类发生变化,子类也需要相应修改。
由于子类是从父类继承而来的,因此它们之间的耦合性非常高。如果我们修改了父类中的某个方法或属性,那么所有的子类都需要相应地进行修改,否则可能会导致程序出错。这种情况下,继承会导致代码的脆弱性和不稳定性。
- 复用不易维护:过度使用继承复用功能,当父类发生改变时,所有子类都需要修改。
虽然继承可以帮助我们实现代码的复用,但是过度使用继承会导致代码的不易维护。当我们在父类中添加新的属性或方法时,所有的子类都需要相应地进行修改。这样会使得代码变得非常复杂,难以维护。此外,过度使用继承还会导致代码的重复,增加代码的大小和复杂度。
总结
总之,通过继承这个代码重用手段,Java类可以解锁父类拥有的属性和方法,就像高手获取新的技能一样。但同时也要注意制造“高度依赖”等问题。明智选择继承,可以让我们的Java之旅更高效而又愉快!