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



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

接下来是可以使用数据服务的方法与服务器通信的常规数据模型:

// 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

有什么办法可以做到这一点吗?

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

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

使用所示代码和所述用例,获得所需行为的唯一方法是根本不进行Model扩展DataService。 有一个替换原则说,如果Model extends DataService,那么有人应该能够像对待DataService实例一样对待Model实例。 事实上,如果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

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


好吧,我有一种沉沦的感觉,你会尝试这个,并对你不能在ModelUser实现中调用this.getAll()感到不安......可能在Modelall()方法的可疑空体内. 我已经有冲动,想防御性地指出最小、完整和可验证的示例文章,因为所述问题似乎不需要这个。

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

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()是一种纯粹的内部方法,从未打算看到曙光。

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

最新更新