я хочу расширить из одного класса, но удалить какое-то свойство

#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"
//}