Có thể sử dụng getters / setters trong định nghĩa giao diện không?


92

Hiện tại, TypeScriptkhông cho phép sử dụng phương thức get / set (trình truy cập) trong giao diện. Ví dụ:

interface I {
      get name():string;
}

class C implements I {
      get name():string {
          return null;
      } 
}

hơn nữa, TypeScript không cho phép sử dụng Biểu thức Hàm Mảng trong các phương thức của lớp: ví dụ:

class C {
    private _name:string;

    get name():string => this._name;
}

Có cách nào khác để tôi có thể sử dụng getter và setter trên định nghĩa giao diện không?

Câu trả lời:


125

Bạn có thể chỉ định thuộc tính trên giao diện, nhưng bạn không thể thực thi liệu getters và setters có được sử dụng hay không, như sau:

interface IExample {
    Name: string;
}

class Example implements IExample {
    private _name: string = "Bob";

    public get Name() {
        return this._name;
    }

    public set Name(value) {
        this._name = value;
    }
}

var example = new Example();
alert(example.Name);

Trong ví dụ này, giao diện không buộc lớp phải sử dụng getters và setters, tôi có thể đã sử dụng một thuộc tính để thay thế (ví dụ bên dưới) - nhưng giao diện được cho là ẩn các chi tiết triển khai này vì nó là một lời hứa với mã gọi về những gì nó có thể gọi.

interface IExample {
    Name: string;
}

class Example implements IExample {
    // this satisfies the interface just the same
    public Name: string = "Bob";
}

var example = new Example();
alert(example.Name);

Và cuối cùng, =>không được phép đối với các phương thức lớp - bạn có thể bắt đầu thảo luận về Codeplex nếu bạn nghĩ rằng có một trường hợp sử dụng khó khăn cho nó. Đây là một ví dụ:

class Test {
    // Yes
    getName = () => 'Steve';

    // No
    getName() => 'Steve';

    // No
    get name() => 'Steve';
}

1
Bạn có thể sử dụng =>để định nghĩa các phương thức của lớp như thế này: name = (a: string) => this._name;nhưng trong JS đầu ra, nó sẽ được định nghĩa bên trong hàm lớp thay vì mở rộng đối tượng nguyên mẫu của nó.
orad

43

Để bổ sung các câu trả lời khác, nếu mong muốn của bạn là xác định một get valuegiao diện, bạn có thể sử dụng readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

class Bar implements Foo {
  get value() {
    return 10;
  }
}

nhưng theo như tôi biết và như những người khác đã đề cập, hiện tại không có cách nào để xác định thuộc tính set-only trong giao diện. Tuy nhiên, bạn có thể chuyển giới hạn thành lỗi thời gian chạy (chỉ hữu ích trong chu kỳ phát triển):

interface Foo {
  /* Set Only! */
  value: number;
}

class Bar implements Foo {
  _value:number;
  set value(value: number) {
    this._value = value;
  }
  get value() {
    throw Error("Not Supported Exception");
  }
}

Không khuyến khích thực hành ; nhưng một tùy chọn.


2

Trước hết, Typecript chỉ hỗ trợ getsetcú pháp khi nhắm mục tiêu Ecmascript 5. Để đạt được điều này, bạn phải gọi trình biên dịch với

tsc --target ES5

Các giao diện không hỗ trợ getters và setters. Để biên dịch mã của bạn, bạn sẽ phải thay đổi nó thành

interface I { 
    getName():string;
}

class C implements I { 
    getName():string {
          return null;
    }   
}

Những gì typecript hỗ trợ là một cú pháp đặc biệt cho các trường trong hàm tạo. Trong trường hợp của bạn, bạn có thể có

interface I {
    getName():string;
}

class C implements I {
    constructor(public name: string) {
    }
    getName():string {
        return name;
    }
}

Chú ý cách lớp Ckhông chỉ định trường name. Nó thực sự được khai báo bằng cách sử dụng đường cú pháp public name: stringtrong hàm tạo.

Như Sohnee đã chỉ ra, giao diện thực sự được cho là ẩn bất kỳ chi tiết triển khai nào. Trong ví dụ của tôi, tôi đã chọn giao diện yêu cầu phương thức getter kiểu java. Tuy nhiên, bạn cũng có thể là một thuộc tính và sau đó để cho lớp quyết định cách triển khai giao diện.


1
Bạn có thể sử dụng getsettừ khóa trong TypeScript.
Fenton

Một lưu ý nhỏ về hỗ trợ ECMAScript 5 - Object.definePropertyđược hỗ trợ trong IE8 +, FF4 +, Opera 12+, WebKit và Safari. Ngoài ra còn có một EC5 Shim tại github.com/kriskowal/es5-shim
Fenton

-1

Sử dụng TypeScript 3.4:

interface IPart {
    getQuantity(): number;
}

class Part implements IPart {
    private quantity: number;
    constructor(quantity: number) {
        this.quantity = quantity;
    }
    public getQuantity = (): number => {
        return this.quantity;
    };
}

let part = new Part(42);

// When used in typescript, quantity is not accessible.
// However, when compiled to javascript it will log '42'.
console.log(part.quantity);

// Logs '42'.
console.log(part.getQuantity());

Xem ví dụ trên TypeScript Playground .

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.