Вызов статического метода из нестатического метода в Typescript - PullRequest
0 голосов
/ 09 октября 2018

У меня есть статические элементы во всей моей иерархии (в этом примере, _image).Я хотел бы иметь возможность доступа к соответствующему _image без необходимости повторять код:

Это было бы здорово:

class Actor {
    static _image; // I need it to be static

    method show(){  // I need it to be non-static
        this.setImage(this.class._image); //doesn't work....
    }
}

class GoodActor extends Actor {
    static _image = 'good.png'
}

class BadActor extends Actor {
    static _image = 'bad.png'
}

class MediumActor extends Actor {
    static _image = 'medium.png'
}

Но это не работает.Прямо сейчас я получил только:

class Actor {
}

class GoodActor extends Actor {
    static _image = 'good.png'  // I need it to be static

    method show(){   // I need it to be non-static
        this.setImage(GoodActor._image);
    }
}

class BadActor extends Actor {
    static _image = 'bad.png'  // I need it to be static

    method show(){  // I need it to be non-static
        this.setImage(BadActor._image);
    }
}

class MediumActor extends Actor {
    static _image = 'medium.png'  // I need it to be static

    method show(){  // I need it to be non-static
        this.setImage(MediumActor._image);
    }
}

Предположим, что у этих четырех классов есть больше методов.Я не хочу повторять метод show() в каждом подклассе ... И все же мне нужен метод show(), чтобы он был нестатичным и _image длябыть статически доступным .

Я прочитал этот вопрос https://github.com/Microsoft/TypeScript/issues/7673, но, к сожалению, я не могу спросить там, поскольку они закрыли его, не исправив.Никто из них не говорил об этой проблеме необходимости динамического разрешения вызываемого статического метода.

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

FTR, вы можете получить доступ к классу текущего объекта.Он называется constructor, а не class, и вам необходимо объявить его, чтобы он имел более полезный тип, чем Function.

class Actor {
    static _image: string; // I need it to be static

    // Keep static members, remove construct signature because
    // subclasses may define constructors with different parameters. 
    "constructor": Pick<typeof Actor, keyof typeof Actor>;

    show(){  // I need it to be non-static
        this.setImage(this.constructor._image);
    }
}

class GoodActor extends Actor {
    static _image = 'good.png'
}

class BadActor extends Actor {
    static _image = 'bad.png'
}

class MediumActor extends Actor {
    static _image = 'medium.png'
}
0 голосов
/ 09 октября 2018

Обновление: Почему вы не хотите создавать отдельные объекты перед кэшированием изображений?Если вы делаете строительство недорогим, использование статических полей бесполезно.

Пример:

class Actor {
    image: string;

    showImage() {
        console.log(this.image);
    }
}


class GoodActor extends Actor {
    image = 'good.png';
}

class BadActor extends Actor {
    image = 'bad.png';
}

const myActorTypes: (typeof Actor)[] = [GoodActor, BadActor];

function preloadImages() {
    for (let myActorType of myActorTypes) {
        preloadImage(new myActorType().image);
    }
}

function preloadImage(image: string) {
    console.log(`Loading ${image}`);
}

preloadImages();

// "Loading good.png"
// "Loading bad.png"

Ответ до уточнения добавлен в комментарии:

К сожалению, это не сработает.Во время выполнения у вас нет возможности ссылаться на класс объекта и, следовательно, нет доступа к статическим полям, если у вас есть только объект, но нет типа для ссылки.

Я, однако, задаюсь вопросом, почему вам нужно иметьстатическое поле.Как я писал в своем комментарии, я никогда не видел хорошего случая использования статических полей для значений, которые на самом деле являются переменными или частью иерархии / наследования объектов.

Я не понимаю ваших точных рассуждений, ноВозможный обходной путь может состоять в том, чтобы передать определенные классы Actor в ваш основной класс Actor и ссылаться на статические поля следующим образом.

type ActorType = { _image: string };

class Actor {
    static _image; // I need it to be static

    actorType: ActorType = null;

    constructor(actorType: ActorType) {
        this.actorType = actorType;
    }

    setImage(image) {
        console.log(`Set image to ${image}`);
    }

    show(){  // I need it to be non-static
        this.setImage(this.actorType._image); //doesn't work....
    }
}

class GoodActor {
    static _image = 'good.png'
}

class BadActor {
    static _image = 'bad.png'
}

class MediumActor {
    static _image = 'medium.png'
}

const actor = new Actor(GoodActor);
actor.show();
// "Set image to good.png"
const actor2 = new Actor(BadActor);
actor2.show();
// "Set image to bad.png"
...