什么是继承?继承的使用以及子类重写父类方法

324 阅读5分钟

继承

在Java中,继承是一种面向对象编程的机制,允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。继承是面向对象编程的三大特性之一,其他两个特性是封装和多态。

继承关键字是什么?怎么使用这个关键字呢?

在Java中,继承关键字是extends。通过使用extends关键字,一个类可以继承另一个类的属性和方法。

下面是一个示例,展示了如何在Java中使用extends关键字来实现继承:

class Animal {  // 父类
    String name;
    
    void eat() {
        System.out.println("动物正在进食");
    }
}

class Dog extends Animal {  // 子类
    void bark() {
        System.out.println("狗在叫");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.name = "旺财";
        myDog.eat();  // 子类继承了父类的eat()方法
        myDog.bark();
    }
}

在上面的示例中,Animal类是一个父类,Dog类是一个子类。子类Dog通过使用extends关键字来继承父类Animal。这意味着Dog类继承了父类Animal的属性name和方法

eat()。子类Dog还定义了自己的方法bark()

main方法中,我们创建了Dog类的一个实例myDog,并通过该实例访问继承自父类的方法eat()和自身定义的方法bark()

需要注意的是,在Java中,一个子类只能继承一个父类,Java不支持多重继承(即一个子类继承多个父类)。如果需要实现多个类的特性,可以考虑使用接口(interface)来达到类似的效果。

子类可以访问父类的哪些成员?

非私有成员

  1. 公共成员(Public Members) :如果父类的成员(字段或方法)被声明为公共(public),则子类可以直接访问这些成员。
  2. 受保护成员(Protected Members) :如果父类的成员被声明为受保护(protected),则子类可以直接访问这些成员。受保护成员对于子类是可见的,但对于其他类不可见。
  3. 默认成员(Default Members) :如果父类的成员没有指定访问修饰符(即默认访问修饰符),则该成员可以在同一个包中的子类中直接访问。然而,如果子类在不同的包中,则默认成员对子类是不可见的。

需要注意的是,私有成员(Private Members)是父类的私有成员对于子类是不可见的,子类无法直接访问父类的私有成员。私有成员只能在父类内部使用。

继承关系中,子类可以继承父类的成员(属性和方法),并且可以通过继承来直接访问这些成员。子类还可以在自己的范围内扩展或修改继承的成员,或者添加自己的新成员。

继承有什么好处?

继承在面向对象编程中具有以下好处:

  1. 代码重用: 继承允许子类继承父类的属性和方法,从而实现代码的重用。子类可以直接使用父类的成员,无需重新编写相同的代码,提高了代码的可维护性和复用性。
  2. 层次结构建立: 通过继承,可以构建类的层次结构。父类可以作为通用概念的抽象表示,而子类可以表示更具体的概念。这种层次结构的建立有助于组织和管理代码,使得代码更加结构化和易于理解。
  3. 多态性: 继承是实现多态性的基础。通过将子类对象赋值给父类引用,可以实现多态的特性。这意味着可以使用父类类型的引用来调用子类对象的方法,根据实际对象的类型来决定执行的具体方法,提供了灵活性和扩展性。
  4. 扩展和修改: 通过继承,子类可以扩展或修改父类的行为。子类可以添加新的属性和方法,或者重写父类的方法来改变其行为。这样可以在不破坏原有代码的情况下,根据需要进行定制和特化,增加了代码的灵活性和可扩展性。
  5. 统一接口: 继承可以实现接口的统一。如果有一组相关的类,它们都继承自同一个父类,那么可以将它们视为具有相同接口的对象。这样可以提高代码的一致性和可替换性,方便在不同的地方使用这些对象。

继承是面向对象编程的核心概念之一,通过合理使用继承,可以提高代码的可重用性、可维护性和可扩展性,同时提供了多态性和代码组织的好处。

子类复写父类方法

当一个子类重写(override)父类的方法时,需要遵循一些规则,如方法名称、参数列表和返回类型必须与父类方法相同。以下是一个示例,展示了在Java中子类如何重写父类的方法:

class Shape {
    public void draw() {
        System.out.println("绘制一个形状");
    }
}

class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制一个圆形");
    }
}

public class Main {
    public static void main(String[] args) {
        Shape shape = new Circle();
        shape.draw(); // 子类重写的方法会被调用
    }
}

在上面的示例中,Shape类是父类,具有一个名为draw()的方法,用于绘制形状。

Circle类是子类,通过重写draw()方法,提供了绘制圆形的实现。在main方法中,我们创建了一个Circle类的实例,并将其赋值给父类Shape类型的变量shape。然后调用shape.draw(),会触发子类Circle中重写的方法,输出"绘制一个圆形"。

注意,我们通过将子类对象赋值给父类引用变量,实现了多态性。这意味着通过父类类型的引用,可以调用子类中重写的方法。

总结起来,子类通过使用@Override注解来明确表示方法是重写的,并且提供与父类方法相同的方法签名(名称、参数列表和返回类型),以重写父类的方法。