如何阻止TypeScript类的属性或方法进行多级继承?

时间:2019-03-11 12:46:52

标签: javascript typescript class inheritance multiple-inheritance

这是下一个JavaScript类结构:

// data.service.ts
export class DataService {
   public url = environment.url;

   constructor(
       private uri: string,
       private httpClient: HttpClient,
   ) { }

   getAll() {}

   getOne(id: number) {}

   create(data: any) {}

   // etc...
}

接下来是通用数据模型,可以使用DataService的方法与服务器进行通信:

// Model.model.ts
import './data.service';

export class Model extends DataService {
    all() {}

    get() {
        // parse and make some basic validation on the
        // DataService.getOne() JSON result
    }

    // etc...
}

最后,我基于Model.model.ts创建一个特定的数据模型:

// User.model.ts
import './Model.model.ts';

export class User extends Model {
    id: number;
    name: string;
    email: string;

    init() {
        // make specific validation on Model.get() result
    }
}

如果我在代码中使用User类,则可以根据需要直接调用DataService的getAll()函数。但这不是一件好事,因为在这种情况下,我会错过内置的验证。

如何阻止对类的方法继承?

我正在寻找类似PHP的static方法。子类可以使用这些方法,但他的孩子不能。

我想要这样的东西:

const dataService = new DataService();
dataService.getAll(); // void

const model = new Model();
model.getAll(); // undefined
model.all();    // void

const user = new User();
user.getAll();  // undefined
user.all();     // void

有什么办法吗?

1 个答案:

答案 0 :(得分:0)

使用所示的代码和所述的用例,获得所需行为的唯一方法是根本不使Model扩展DataService。有一个subsitution principle表示如果使用Model extends DataService,那么某人应该能够像对待Model实例一样对待DataService实例。确实,如果ModelDataService的特殊类型,并且有人要求一个DataService实例,那么您应该可以给他们一个Model。告诉他们他们不能在其上调用getAll()方法是不公平的。因此,继承树无法像您那样拥有它。相反,您可以执行以下操作:

// ultimate parent class of both DataService and Model/User 
class BaseDataService {
  getOne(id: number) { }
  create(data: any) { }
  // etc...
}

// subclass with getAll()
class DataService extends BaseDataService {
  getAll() {}
}


// subclass without getAll()
class Model extends BaseDataService {
  all() { }
  get() { }
  // etc...
}

class User extends Model {
  id!: number;
  name!: string;
  email!: string;
  init() { }
}

const dataService = new DataService();
dataService.getAll(); // void

const model = new Model();
model.getAll(); // error
model.all();    // okay

const user = new User();
user.getAll();  // error
user.all();     // okay

完全按照您指定的方式工作。完美吧?


好吧,我有种下沉的感觉,您将尝试此操作并感到沮丧,因为您无法在this.getAll()Model实现中调用User。 ..可能位于all()中的Model方法的可疑空体内。而且,我已经急于防御性地指向Minimum, Complete, and Verifiable Example文章,因为问题 似乎并不需要。

如果确实需要这样做,您仍然不能违反替代原则。相反,我建议将getAll()设为protected方法,并在all()上公开DataService方法:

class DataService {
  getOne(id: number) { }
  create(data: any) { }
  protected getAll() { }
  all() { 
    this.getAll();
  }
  // etc...
}

class Model extends DataService {
  all() {
    this.getAll();
  }
  get() { }
  // etc...
}

class User extends Model {
  id!: number;
  name!: string;
  email!: string;
  init() { }
}

const dataService = new DataService();
dataService.getAll(); // error
dataService.all(); // okay

const model = new Model();
model.getAll(); // error
model.all();    // okay

const user = new User();
user.getAll();  // error
user.all();     // okay

并遵循getAll()是纯粹内部方法的事实,而这绝不意味着日日夜夜。

好的,希望其中之一能有所帮助;祝你好运!