#javascript #angular #typescript #class #oop
Вопрос:
У меня есть некоторый класс для класса обслуживания crud API, я хочу его расширить, но для экзамена у меня мало свойств, это мой класс
Class Parent {
public propertyToKeep: any;
public propertyToDelete: any;
constructor() {}
}
это детский класс
Class Child extend Parent {
constructor() {
super();
}
}
Еще один файл
, который я не хочу видеть и к которому не хочу получать доступ
export class SomeComponent {
constructor(private child: Child) {
this.child.propertyToKeep // work
this.child.propertyToDelete // error and I can't even see it
}
}
Комментарии:
1. Так в чем же проблема? вы расширили класс, но не видите некоторые свойства в дочернем классе?
2. Это невозможно. Дочерний класс-это полный родительский класс. Вот как работает наследование ООП. JavaScript и машинопись поддерживают полиморфизм . Это требует, чтобы каждый подтип имел свойства и методы своего родителя.
3. лучшее решение, которое я предлагаю, — создать промежуточный класс под названием «SharedClass», который будет родительским для двух классов : ParentClass и ChildClass, который будет содержать только «общие свойства», например, вы сможете расширить его напрямую и сохранить родительские свойства для своих целей .
4. Вы могли бы вернуться к прототипам JavaScript. Там вы можете наследовать и удалять свойства.
Ответ №1:
Просто наткнулся на тот же вариант использования, что и вы, и вот как я это делаю :
const Omit = <T, K extends keyof T>(Class: new () => T, keys: K[]): new () => Omit<T, typeof keys[number]> =>
Class;
тогда вы можете использовать его так :
class Child extends Omit(Parent, ['propertyToDelete']), {}
как вы можете видеть, у chlid теперь есть только одно свойство (оно также работает с методами).
В пакете от @nestjs/swagger есть несколько хороших помощников, если вы имеете дело с API NestJS. Их реализация более сложна, поэтому я предполагаю, что они хранят другие вещи, такие как их собственные декораторы свойств (я довольно новичок в машинописи, поэтому, возможно, я упускаю смысл всего, что они делают).
P. S: Первый ответ француз, так что не идеальный английский, пожалуйста, будьте добры ^^
Ответ №2:
Это невозможно. Если вы объявите атрибут в родительском классе, вы не сможете ограничить его видимость в дочернем классе.
С точки зрения дизайна модели это тоже не имеет смысла. Проблема, которую вы здесь описываете, указывает на то, что ваша иерархия классов не очень хорошо разработана, и вы должны переосмыслить и перепроектировать ее.
Ответ №3:
Вам нужно использовать Object.defineProperty
функцию, чтобы сделать ограничение в дескрипторе, перечисляемым до false и getter
, setter
с определенным условием, вот полный пример:
//A small example of how to make an invisible property in Child class.
class Parent{
constructor(){
this.propertyToKeep = "Visible";
this.propertyToDelete = "Not visible in subclass child";
}
}
Object.defineProperty(Parent.prototype, "propertyToDelete", {enumerable: false,
configurable: true,
get: function(){
if(!(this instanceof Child)){
return this._propertyToDelete;
}
},
set: function(v){
if(!(this instanceof Child)){
this._propertyToDelete = v;
}
}});
Object.freeze(Parent.prototype);
class Child extends Parent {
constructor() {
super();
}
}
//console.log(Child.prototype);
let chd = new Child();
console.log("Child: --------------------------------");
console.log(chd);
console.log(chd.propertyToDelete); //Undefined
console.log("Parent: -------------------------------");
let prt = new Parent();
console.log(prt);
console.log(prt.propertyToDelete); //"Not visible in subclass child"
/*let chdObj = Object.getOwnPropertyDescriptors(Child.prototype);
console.log(chdObj);*/
class SomeComponent{
#child;
constructor(child) {
this.#child = child;
console.log(this.#child); //{propertyToKeep: "Visible"}
console.log(this.#child.propertyToKeep /*work*/);
console.log(this.#child.propertyToDelete /*undefined*/);
}
}
//Now i will invoke SomeComponent
console.log("SomeComponent: -------------------------");
let sc = new SomeComponent(new Child());
Комментарии:
1. Спасибо, но в этом случае мне нужно использовать его иногда с атрибутом, а иногда и без него. Мне нужно использовать его в инъекции угловой зависимости. Так что никакой пользы от конструктора. Я проверю, может быть, я смогу войти с этим, чтобы получить свой гол, большое вам спасибо
Ответ №4:
Вот один из способов сделать это:
class Parent {
propertyToKeep = 'hi';
propertyToDelete = 'bye';
constructor() {}
}
class Child extends Parent {
constructor() {
super();
delete this.propertyToDelete;
}
}
const myObject = new Child();
console.log(myObject);
//{
// "propertyToKeep": "hi"
//}