MST

星途 面试题库

面试题:TypeScript封装机制与继承中的访问修饰符

假设你有一个基类`Animal`,包含一些属性和方法,部分使用了不同的访问修饰符。现在创建一个子类`Dog`继承自`Animal`,请详细阐述在子类中访问基类成员时,不同访问修饰符(public、private、protected)的访问规则,以及如何在子类中正确重写或扩展基类方法以维持封装性。同时给出相应的代码示例。
10.4万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

访问修饰符访问规则

  1. public(公共的)
    • 在基类Animal中声明为public的成员(属性和方法),在子类Dog中可以直接访问。这意味着在子类的方法内部可以调用基类的public方法,也可以访问基类的public属性。
    • 从外部代码来看,无论是基类对象还是子类对象,都可以访问其public成员。
  2. private(私有的)
    • 在基类Animal中声明为private的成员,在子类Dog中无法直接访问。即使子类继承自基类,也不能访问基类的private成员。这是为了保证封装性,防止外部(包括子类)对内部实现细节的直接访问。
    • 外部代码同样无法访问基类或子类对象的private成员。
  3. protected(受保护的)
    • 在基类Animal中声明为protected的成员,在子类Dog中可以直接访问。与public不同的是,外部代码不能直接访问基类或子类对象的protected成员,只有子类内部可以访问。这提供了一种介于publicprivate之间的访问级别,允许子类访问一些基类的内部成员,但限制外部访问。

重写或扩展基类方法维持封装性

  1. 重写(Override)
    • 当子类需要改变基类方法的行为时,可以重写该方法。在重写方法时,方法的签名(方法名、参数列表、返回类型)必须与基类中被重写的方法完全相同(在Java中,返回类型可以是协变的,即子类重写方法的返回类型可以是基类方法返回类型的子类)。
    • 重写方法时,访问修饰符不能比基类中被重写方法的访问修饰符更严格。例如,如果基类方法是public,子类重写方法不能是protectedprivate
  2. 扩展
    • 子类可以在重写方法中通过调用super关键字来调用基类的方法,从而在基类方法的基础上进行功能扩展。这样既利用了基类已有的功能,又增加了子类特有的功能,同时维持了封装性。

代码示例(以Java语言为例)

class Animal {
    private String name;
    protected int age;
    public String color;

    public Animal(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public void eat() {
        System.out.println(name + " is eating.");
    }

    private void sleep() {
        System.out.println(name + " is sleeping.");
    }
}

class Dog extends Animal {
    public Dog(String name, int age, String color) {
        super(name, age, color);
    }

    @Override
    public void eat() {
        // 扩展基类的eat方法
        super.eat();
        System.out.println(name + " is eating dog food.");
    }

    public void play() {
        // 可以访问protected属性age
        System.out.println(name + " which is " + age + " years old is playing.");
        // 不能访问private方法sleep()
        // sleep(); 这行代码会报错
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy", 3, "Brown");
        dog.eat();
        dog.play();
        // 可以访问public属性color
        System.out.println("Dog's color is " + dog.color);
        // 不能访问private属性name
        // System.out.println("Dog's name is " + dog.name); 这行代码会报错
    }
}

上述代码中,Animal类是基类,Dog类继承自AnimalDog类重写了eat方法并进行了扩展,同时展示了不同访问修饰符成员在子类中的访问情况。