Truy cập thành viên của lớp cơ sở


118

Xem ví dụ kế thừa từ sân chơi trên trang TypeScript:

class Animal {
  public name;
  constructor(name) {
    this.name = name;
  }
  move(meters) {
    alert(this.name + " moved " + meters + "m.");
  }
}

class Snake extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert("Slithering...");
    super.move(5);
  }
}

class Horse extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert(super.name + " is Galloping...");
    super.move(45);
  }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

Tôi đã thay đổi một dòng mã: cảnh báo trong Horse.move(). Ở đó tôi muốn truy cập super.name, nhưng nó chỉ trả về undefined. IntelliSense gợi ý rằng tôi có thể sử dụng nó và TypeScript biên dịch tốt, nhưng nó không hoạt động.

Có ý kiến ​​gì không?

Câu trả lời:


179

Ví dụ làm việc. Ghi chú bên dưới.

class Animal {
    constructor(public name) {
    }

    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    move() {
        alert(this.name + " is Slithering...");
        super.move(5);
    }
}

class Horse extends Animal {
    move() {
        alert(this.name + " is Galloping...");
        super.move(45);
    }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);
  1. Bạn không cần phải gán tên cho một biến công khai theo cách thủ công. Sử dụng public nametrong định nghĩa hàm tạo sẽ thực hiện điều này cho bạn.

  2. Bạn không cần phải gọi super(name)từ các lớp chuyên ngành.

  3. Sử dụng this.namecông trình.

Lưu ý khi sử dụng super.

Điều này được đề cập chi tiết hơn trong phần 4.9.2 của đặc tả ngôn ngữ.

Hành vi của các lớp kế thừa từ Animalkhông khác với hành vi trong các ngôn ngữ khác. Bạn cần chỉ định supertừ khóa để tránh nhầm lẫn giữa hàm chuyên biệt và hàm lớp cơ sở. Ví dụ, nếu bạn đã gọi move()hoặc this.move()bạn sẽ xử lý chuyên biệt Snakehoặc Horsehàm, do đó, sử dụng super.move()các lệnh gọi hàm lớp cơ sở một cách rõ ràng.

Không có sự nhầm lẫn của các thuộc tính, vì chúng là các thuộc tính của cá thể. Không có sự khác biệt giữa super.namethis.name- đơn giản là có this.name. Nếu không, bạn có thể tạo Ngựa có các tên khác nhau tùy thuộc vào việc bạn học ở lớp chuyên hay lớp cơ sở.


Câu trả lời tuyệt vời, và cảm ơn bạn đã tham khảo đặc tả ngôn ngữ. Bạn có biết bất kỳ tài liệu nào về lý do tại sao, chẳng hạn, các trình truy cập thuộc tính lớp cơ sở không được ảo hóa và có thể truy cập được thông qua ghi đè các trình truy cập trong lớp dẫn xuất (như các phương thức)?
David Cuccia

Mục 4.8 bao gồm tất cả mọi thứ đã được viết ra cho đến nay - nó có xu hướng là "đây là hành vi", mặc dù thay vì "đây là lý do tại sao".
Fenton

3
Cảm ơn Steve Fenton. Tôi cũng vừa tình cờ gặp một cuộc thảo luận tương tự tại đây: stylescript.codeplex.com/discussions/418349 . Có vẻ là sự mất cân bằng trong ngôn ngữ; tôi đoán là quyết định được đưa ra để giữ cho JavaScript được phát ra đơn giản, trái ngược với các phương thức trợ giúp "làm việc xung quanh" để bù đắp cho việc thiếu hỗ trợ JavaScript.
David Cuccia

1

Bạn đang sử dụng từ khóa supervà không chính xác this. Đây là một ví dụ về cách chúng hoạt động:

class Animal {
    public name: string;
    constructor(name: string) { 
        this.name = name;
    }
    move(meters: number) {
        console.log(this.name + " moved " + meters + "m.");
    }
}

class Horse extends Animal {
    move() {
        console.log(super.name + " is Galloping...");
        console.log(this.name + " is Galloping...");
        super.move(45);
    }
}

var tom: Animal = new Horse("Tommy the Palomino");

Animal.prototype.name = 'horseee'; 

tom.move(34);
// Outputs:

// horseee is Galloping...
// Tommy the Palomino is Galloping...
// Tommy the Palomino moved 45m.

Giải trình:

  1. Đầu ra nhật ký đầu tiên super.name, điều này đề cập đến chuỗi nguyên mẫu của đối tượng tom, không phải tombản thân đối tượng . Bởi vì chúng tôi đã thêm một thuộc tính tên trên Animal.prototype, nên sẽ xuất ra đoạn mã.
  2. Bản ghi thứ hai xuất ra this.name, thistừ khóa đề cập đến chính đối tượng tom.
  3. Nhật ký thứ ba được ghi bằng movephương thức của lớp cơ sở Animal. Phương thức này được gọi từ phương thức di chuyển lớp Horse với cú pháp super.move(45);. Sử dụng supertừ khóa trong ngữ cảnh này sẽ tìm kiếm một movephương thức trên chuỗi nguyên mẫu được tìm thấy trên nguyên mẫu Động vật.

Hãy nhớ rằng TS vẫn sử dụng các nguyên mẫu classextendstừ khóa và từ khóa chỉ là đường cú pháp thay vì kế thừa nguyên mẫu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.