Java继承机制「详解」

前言:在生活中,我们常会羡慕身边的“高手”。比如羽毛球高手轻松接下别人的杀手锏,乒乓球高手胶着情况下“神来之笔”打出妙球。这都是因为高手具备我们没有的技能。那么,在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类,我们的类仍然会默认继承它。

继承的好处:

想必经过上面的介绍,一定可以理清为什么要使用继承了吧!它主要有以下的优点:

  1. 重用代码:子类可以复用父类的属性和方法,无需重复编写。
  2. 扩展功能:子类在继承父类的同时,可以添加新的属性和方法,扩展其功能。
  3. 类型兼容:子类是父类的一种类型,这种类型兼容性帮助方法的重载选择。
  4. 多态:继承是实现多态的基础,让子类对象可以当成父类对象使用。

继承的缺点:

当然继承机制也有其缺点

  1. 耦合性高:子类高度依赖父类,一旦父类发生变化,子类也需要相应修改。

由于子类是从父类继承而来的,因此它们之间的耦合性非常高。如果我们修改了父类中的某个方法或属性,那么所有的子类都需要相应地进行修改,否则可能会导致程序出错。这种情况下,继承会导致代码的脆弱性和不稳定性。

  1. 复用不易维护:过度使用继承复用功能,当父类发生改变时,所有子类都需要修改。

虽然继承可以帮助我们实现代码的复用,但是过度使用继承会导致代码的不易维护。当我们在父类中添加新的属性或方法时,所有的子类都需要相应地进行修改。这样会使得代码变得非常复杂,难以维护。此外,过度使用继承还会导致代码的重复,增加代码的大小和复杂度。

总结

总之,通过继承这个代码重用手段,Java类可以解锁父类拥有的属性和方法,就像高手获取新的技能一样。但同时也要注意制造“高度依赖”等问题。明智选择继承,可以让我们的Java之旅更高效而又愉快!

猜你喜欢

转载自blog.csdn.net/weixin_56433857/article/details/131176416