programing

TypeScript에서 추상 메서드를 선언하는 중

lastmemo 2023. 3. 27. 20:57
반응형

TypeScript에서 추상 메서드를 선언하는 중

TypeScript에서 추상 메서드를 올바르게 정의하는 방법을 찾고 있습니다.

원본 상속 예를 사용하여 다음을 수행합니다.

class Animal {
    constructor(public name) { }
    makeSound(input : string) : string;
    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    constructor(name) { super(name); }
    makeSound(input : string) : string {
        return "sssss"+input;
    }
    move() {
        alert("Slithering...");
        super.move(5);
    }
}

make Sound 메서드를 올바르게 정의하여 입력해서 덮어쓸 수 있도록 하는 방법을 알고 싶습니다.

어떻게 해야 할지 잘 요.protectedmethods - 키워드처럼 보이지만 효과가 없고 코드가 컴파일되지 않습니다.

name은 ""로 되어 있습니다.protectedTypeScript 1.3을 사용합니다.

makeSound는 method로 됩니다.abstract이치노할 수 .Animal왜냐하면 추상적이기 때문입니다.이것은 TypeScript 1.6의 일부이며, 현재 공식적으로 가동되고 있습니다.

abstract class Animal {
    constructor(protected name: string) { }

    abstract makeSound(input : string) : string;

    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }

    makeSound(input : string) : string {
        return "sssss"+input;
    }

    move() {
        alert("Slithering...");
        super.move(5);
    }
}

추상적인 방법을 모방하는 오래된 방법은 누군가 그것을 사용하면 오류를 범하는 것이었다.프로젝트에 TypeScript 1.6이 도착하면 더 이상 이 작업을 수행할 필요가 없습니다.

class Animal {
    constructor(public name) { }
    makeSound(input : string) : string {
        throw new Error('This method is abstract');
    }
    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    constructor(name) { super(name); }
    makeSound(input : string) : string {
        return "sssss"+input;
    }
    move() {
        alert("Slithering...");
        super.move(5);
    }
}

Erics의 답변을 조금 더 진행하면 다형성을 완전히 지원하고 기본 클래스에서 구현된 메서드를 호출할 수 있는 기능을 통해 추상 클래스의 꽤 괜찮은 구현을 실제로 만들 수 있습니다.코드부터 시작합시다.

/**
 * The interface defines all abstract methods and extends the concrete base class
 */
interface IAnimal extends Animal {
    speak() : void;
}

/**
 * The abstract base class only defines concrete methods & properties.
 */
class Animal {

    private _impl : IAnimal;

    public name : string;

    /**
     * Here comes the clever part: by letting the constructor take an 
     * implementation of IAnimal as argument Animal cannot be instantiated
     * without a valid implementation of the abstract methods.
     */
    constructor(impl : IAnimal, name : string) {
        this.name = name;
        this._impl = impl;

        // The `impl` object can be used to delegate functionality to the
        // implementation class.
        console.log(this.name + " is born!");
        this._impl.speak();
    }
}

class Dog extends Animal implements IAnimal {
    constructor(name : string) {
        // The child class simply passes itself to Animal
        super(this, name);
    }

    public speak() {
        console.log("bark");
    }
}

var dog = new Dog("Bob");
dog.speak(); //logs "bark"
console.log(dog instanceof Dog); //true
console.log(dog instanceof Animal); //true
console.log(dog.name); //"Bob"

★★★★★★★★★★★★★★★★★.Animal에서는, 「이행하다」의 이 필요합니다.IAnimal활자의 물체를 만드는 것은 불가능하다Animal추상적 방법을 제대로 구현하지 못한 경우.하기 위해서는 '다형성', '다형성', '다형성', '다형성'의 예를 .IAnimal 아니라, 이에요.Animal예:

//This works
function letTheIAnimalSpeak(animal: IAnimal) {
    console.log(animal.name + " says:");
    animal.speak();
}
//This doesn't ("The property 'speak' does not exist on value of type 'Animal')
function letTheAnimalSpeak(animal: Animal) {
    console.log(animal.name + " says:");
    animal.speak();
}

Erics 답변과의 주요 차이점은 "추상" 기본 클래스는 인터페이스를 구현해야 하므로 그 자체로는 인스턴스화할 수 없다는 것입니다.

인터페이스와 기본 클래스를 조합하여 사용하면 도움이 될 수 있다고 생각합니다.컴파일 시 동작요건을 적용합니다(rq_post "아래"는 위의 게시물을 의미하지만, 이 게시물은 해당 게시물이 아닙니다).

인터페이스는 기본 클래스가 충족하지 않는 동작 API를 설정합니다.인터페이스에 정의되어 있는 메서드를 호출하도록 베이스 클래스의 메서드를 설정할 수 없습니다(이러한 동작을 정의하지 않으면 그 인터페이스를 베이스 클래스에 실장할 수 없습니다.부모 인터페이스 메서드를 호출할 수 있는 안전한 방법을 생각해 낼 수 있습니다.

인스턴스화할 클래스를 확장하고 구현하는 것을 기억해야 합니다.런타임 실패 코드 정의에 대한 우려를 충족합니다.또한 인터페이스를 구현하지 않으면(Animal 클래스를 인스턴스화하려고 하는 경우 등) 토하는 메서드를 호출할 수도 없습니다.아래의 BaseAnimal을 확장하도록 인터페이스를 설정하려고 했지만, BaseAnimal의 컨스트럭터와 이름 필드를 Snake로부터 숨겼습니다.만약 그렇게 할 수 있었다면 모듈 및 export를 사용하면 Base Animal 클래스의 우발적인 직접 인스턴스화를 방지할 수 있었을 것입니다.

여기에 붙여넣기하여 고객에게 적합한지 확인하십시오.http://www.typescriptlang.org/Playground/

// The behavioral interface also needs to extend base for substitutability
interface AbstractAnimal extends BaseAnimal {
    // encapsulates animal behaviors that must be implemented
    makeSound(input : string): string;
}

class BaseAnimal {
    constructor(public name) { }

    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

// If concrete class doesn't extend both, it cannot use super methods.
class Snake extends BaseAnimal implements AbstractAnimal {
    constructor(name) { super(name); }
    makeSound(input : string): string {
        var utterance = "sssss"+input;
        alert(utterance);
        return utterance;
    }
    move() {
        alert("Slithering...");
        super.move(5);
    }
}

var longMover = new Snake("windy man");

longMover.makeSound("...am I nothing?");
longMover.move();

var fulture = new BaseAnimal("bob fossil");
// compile error on makeSound() because it is not defined.
// fulture.makeSound("you know, like a...")
fulture.move(1);

아래 링크된 FristvanCampen의 답변을 우연히 발견했습니다.그는 추상 클래스는 안티패턴이라며 구현 클래스의 주입된 인스턴스를 사용하여 기본 '추상' 클래스를 인스턴스화할 것을 제안합니다.이것은 공평하지만, 반론이 있다.직접 읽어보십시오.https://typescript.codeplex.com/discussions/449920

파트 2: 추상 클래스를 원하는 다른 케이스가 있었지만, 위의 솔루션을 사용할 수 없었습니다.왜냐하면 "추상 클래스"에서 정의된 메서드는 일치하는 인터페이스에 정의된 메서드를 참조할 필요가 있었기 때문입니다.그래서 프리스반캠펜의 조언을 따르죠저는 메서드 구현과 함께 불완전한 "추상" 클래스를 가지고 있습니다.구현되지 않은 메서드와의 인터페이스가 있습니다.이 인터페이스는 "추상" 클래스를 확장합니다.그런 다음 첫 번째 클래스를 확장하고 두 번째 클래스를 구현합니다(그렇지 않으면 슈퍼 컨스트럭터에 액세스할 수 없기 때문에 둘 다 확장해야 합니다).다음의 (실행 불가) 예를 참조해 주세요.

export class OntologyConceptFilter extends FilterWidget.FilterWidget<ConceptGraph.Node, ConceptGraph.Link> implements FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link> {

    subMenuTitle = "Ontologies Rendered"; // overload or overshadow?

    constructor(
        public conceptGraph: ConceptGraph.ConceptGraph,
        graphView: PathToRoot.ConceptPathsToRoot,
        implementation: FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link>
        ){
        super(graphView);
        this.implementation = this;
    }
}

그리고.

export class FilterWidget<N extends GraphView.BaseNode, L extends GraphView.BaseLink<GraphView.BaseNode>> {

    public implementation: IFilterWidget<N, L>

    filterContainer: JQuery;

    public subMenuTitle : string; // Given value in children

    constructor(
        public graphView: GraphView.GraphView<N, L>
        ){

    }

    doStuff(node: N){
        this.implementation.generateStuff(thing);
    }

}

export interface IFilterWidget<N extends GraphView.BaseNode, L extends GraphView.BaseLink<GraphView.BaseNode>> extends FilterWidget<N, L> {

    generateStuff(node: N): string;

}

난 기본반에서 예외를 두곤 했어.

protected abstractMethod() {
    throw new Error("abstractMethod not implemented");
}

그런 다음 하위 클래스에서 구현해야 합니다.단점은 빌드 오류는 없지만 런타임이라는 것입니다.장점은 이 메서드를 슈퍼클래스에서 호출할 수 있다는 것입니다.이 메서드는 동작한다고 가정하면 다음과 같습니다.

HTH!

밀턴

안돼, 안돼, 안돼!언어가 해당 기능을 지원하지 않는 경우 자체 '추상' 클래스 및 메서드를 만들지 마십시오. 특정 언어를 지원하고자 하는 모든 언어 기능에서도 마찬가지입니다.TypeScript에서 추상 메서드를 구현하는 올바른 방법은 없습니다.특정 클래스가 이 금지사항을 명시적으로 적용하지 않고 직접 인스턴스화되지 않도록 명명 규칙을 사용하여 코드를 구성하기만 하면 됩니다.

또한 위의 예에서는 Java/C#에서 예상되는 대로 컴파일 시간이 아닌 실행 시간에만 이 적용을 제공합니다.

언급URL : https://stackoverflow.com/questions/13333489/declaring-abstract-method-in-typescript

반응형