Как заблокировать свойство класса TypeScript или метод многоуровневого наследования метода? - PullRequest
0 голосов
/ 11 марта 2019

Вот следующая структура класса 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 в своем коде, я могу напрямую вызвать функцию getAll () DataService, если захочу. Но это не очень хорошая вещь, потому что в этом случае мне не хватает встроенных проверок.

Как заблокировать наследование метода в классе?

Я ищу что-то похожее на 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

Есть ли способ сделать это?

Ответы [ 2 ]

0 голосов
/ 11 марта 2019

С вашим кодом, как показано, и вариантом использования, как указано, единственный способ получить желаемое поведение - не заставлять Model расширять DataService вообще.Существует принцип подстановки , который гласит, что если 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 и 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() это чисто внутренний метод, никогда не предназначенный для того, чтобы увидеть дневной свет.

Хорошо, надеюсь, один из них поможет;удачи!

0 голосов
/ 11 марта 2019

Вы можете запретить его построение при вызове, добавив ключевое слово private в функцию private getAll() {}.Но private - это функция TypeScript, а не Javascript, поэтому, если вы заставите ее создать, она все равно будет вызываться.В этот момент не будет никакого способа полностью предотвратить это.

Поэтому, если вы хотите, чтобы это было предотвращено в TypeScript, просто добавьте туда ключевое слово private.Но это не компилируется, не возвращает неопределенный, как вы ожидаете.В противном случае просто замените функцию неопределенной возвращаемой функцией в дочерних классах

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...