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

问题描述 投票:0回答:2

这是下一个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

有没有办法做到这一点?

javascript typescript class inheritance multiple-inheritance
2个回答
0
投票

通过将private关键字添加到函数private getAll() {}来调用它时,可以阻止它的构建。但private是一个TypeScript功能,而不是Javascript,所以如果强制它构建,它仍然是可调用的。这一刻没有办法完全阻止它。

因此,如果您希望在TypeScript中阻止它,只需在那里添加private关键字。但它不是可构建的,不会像你期望的那样返回undefined。否则,只需在子类上使用未定义返回的函数替换该函数


0
投票

使用所示的代码和使用案例,获得所需行为的唯一方法就是不要让Model扩展DataService。有一个subsitution principle说,如果Model extends DataService,那么有人应该能够像对待Model实例一样对待DataService实例。事实上,如果Model是一种特殊类型的DataService,有人要求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()是一种纯粹的内部方法,从来没有意味着看到光明的一天。

好的,希望其中一个有帮助;祝好运!

© www.soinside.com 2019 - 2024. All rights reserved.