정적 메소드를 호출하는 표준 방법은 무엇입니까? 나는 constructor
클래스 자체의 이름 을 사용 하거나 사용할 것을 생각할 수 있습니다 . 필요하지 않다고 생각하기 때문에 후자를 좋아하지 않습니다. 전자가 권장되는 방법입니까, 아니면 다른 것이 있습니까?
다음은 (고려 된) 예입니다.
class SomeObject {
constructor(n){
this.n = n;
}
static print(n){
console.log(n);
}
printN(){
this.constructor.print(this.n);
}
}
답변
두 방법 모두 실행 가능하지만 재정의 된 정적 메서드를 사용하여 상속 할 때 다른 작업을 수행합니다. 행동이 예상되는 것을 선택하십시오 :
class Super {
static whoami() {
return "Super";
}
lognameA() {
console.log(Super.whoami());
}
lognameB() {
console.log(this.constructor.whoami());
}
}
class Sub extends Super {
static whoami() {
return "Sub";
}
}
new Sub().lognameA(); // Super
new Sub().lognameB(); // Sub
클래스를 통해 정적 속성을 참조하면 실제로 정적이며 지속적으로 동일한 값을 제공합니다. 사용하여 this.constructor
동적 파견을 사용하고 정적 속성은 현재 인스턴스의 클래스를 참조 할 대신 할 수 상속 된 값을 가질뿐만 아니라, 오버라이드 (override) 할 수 있습니다.
이것은 클래스 이름이나 instance를 통해 정적 속성을 참조하도록 선택할 수있는 Python의 동작과 일치합니다 self
.
Java 에서처럼 정적 특성이 대체되지 않고 항상 현재 클래스 중 하나를 참조 할 것으로 예상되는 경우 명시 적 참조를 사용하십시오.
답변
비슷한 사례에 대한 답을 찾기 위해이 스레드를 우연히 발견했습니다. 기본적으로 모든 답변이 있지만 여전히 필수 답변을 추출하기는 어렵습니다.
접근의 종류
아마도 다른 클래스에서 파생 된 Foo 클래스가 더 많은 클래스에서 파생되었다고 가정하십시오.
그런 다음
- Foo의 정적 메소드 / getter에서
- 아마도 재정의 된 정적 메소드 / getter :
this.method()
this.property
- 아마도 재정의 된 인스턴스 메소드 / getter :
- 의도적으로 불가능
- 자신의 오버라이드 (override)되지 않는 정적의 방법 / 게터 :
Foo.method()
Foo.property
- 재정의되지 않은 자체 인스턴스 메소드 / 게터 :
- 의도적으로 불가능
- 아마도 재정의 된 정적 메소드 / getter :
- Foo의 인스턴스 메소드 / getter에서
- 아마도 재정의 된 정적 메소드 / getter :
this.constructor.method()
this.constructor.property
- 아마도 재정의 된 인스턴스 메소드 / getter :
this.method()
this.property
- 자신의 오버라이드 (override)되지 않는 정적의 방법 / 게터 :
Foo.method()
Foo.property
- 재정의되지 않은 자체 인스턴스 메소드 / 게터 :
- 해결 방법을 사용하지 않으면 의도적으로 불가능합니다 .
Foo.prototype.method.call( this )
Object.getOwnPropertyDescriptor( Foo.prototype,"property" ).get.call(this);
- 해결 방법을 사용하지 않으면 의도적으로 불가능합니다 .
- 아마도 재정의 된 정적 메소드 / getter :
사용하는 것을 명심
this
화살표 기능을 사용하거나 메소드를 호출 할 때이 방법을 작동하지 않습니다 / 게터가 명시 적으로 사용자 정의 값에 바인딩.
배경
- 인스턴스의 메소드 또는 getter와 관련하여
this
현재 인스턴스를 참조하고 있습니다.super
기본적으로 동일한 인스턴스를 참조하지만 현재 일부 클래스와 관련하여 작성된 메서드 및 getter를 다소 확장하고 있습니다 (Foo 프로토 타입의 프로토 타입을 사용하여).- 인스턴스 생성에 사용 된 인스턴스 클래스의 정의는에 따라 제공됩니다
this.constructor
.
- 정적 메소드 또는 getter와 관련하여 의도적으로 “현재 인스턴스”가없는 경우
this
현재 클래스의 정의를 직접 참조 할 수 있습니다.super
일부 인스턴스를 참조하는 것이 아니라 현재 일부 클래스의 컨텍스트에서 작성된 정적 메소드 및 getter가 확장되고 있습니다.
결론
이 코드를 사용해보십시오 :
class A {
constructor( input ) {
this.loose = this.constructor.getResult( input );
this.tight = A.getResult( input );
console.log( this.scaledProperty, Object.getOwnPropertyDescriptor( A.prototype, "scaledProperty" ).get.call( this ) );
}
get scaledProperty() {
return parseInt( this.loose ) * 100;
}
static getResult( input ) {
return input * this.scale;
}
static get scale() {
return 2;
}
}
class B extends A {
constructor( input ) {
super( input );
this.tight = B.getResult( input ) + " (of B)";
}
get scaledProperty() {
return parseInt( this.loose ) * 10000;
}
static get scale() {
return 4;
}
}
class C extends B {
constructor( input ) {
super( input );
}
static get scale() {
return 5;
}
}
class D extends C {
constructor( input ) {
super( input );
}
static getResult( input ) {
return super.getResult( input ) + " (overridden)";
}
static get scale() {
return 10;
}
}
let instanceA = new A( 4 );
console.log( "A.loose", instanceA.loose );
console.log( "A.tight", instanceA.tight );
let instanceB = new B( 4 );
console.log( "B.loose", instanceB.loose );
console.log( "B.tight", instanceB.tight );
let instanceC = new C( 4 );
console.log( "C.loose", instanceC.loose );
console.log( "C.tight", instanceC.tight );
let instanceD = new D( 4 );
console.log( "D.loose", instanceD.loose );
console.log( "D.tight", instanceD.tight );
답변
어떤 종류의 상속을 계획하고 있다면 권장 this.constructor
합니다. 이 간단한 예는 이유를 설명해야합니다.
class ConstructorSuper {
constructor(n){
this.n = n;
}
static print(n){
console.log(this.name, n);
}
callPrint(){
this.constructor.print(this.n);
}
}
class ConstructorSub extends ConstructorSuper {
constructor(n){
this.n = n;
}
}
let test1 = new ConstructorSuper("Hello ConstructorSuper!");
console.log(test1.callPrint());
let test2 = new ConstructorSub("Hello ConstructorSub!");
console.log(test2.callPrint());
test1.callPrint()
ConstructorSuper Hello ConstructorSuper!
콘솔에 기록 합니다test2.callPrint()
ConstructorSub Hello ConstructorSub!
콘솔에 기록 합니다
명명 된 클래스는 명명 된 클래스를 참조하는 모든 함수를 명시 적으로 재정의하지 않는 한 상속을 잘 처리하지 않습니다. 예를 들면 다음과 같습니다.
class NamedSuper {
constructor(n){
this.n = n;
}
static print(n){
console.log(NamedSuper.name, n);
}
callPrint(){
NamedSuper.print(this.n);
}
}
class NamedSub extends NamedSuper {
constructor(n){
this.n = n;
}
}
let test3 = new NamedSuper("Hello NamedSuper!");
console.log(test3.callPrint());
let test4 = new NamedSub("Hello NamedSub!");
console.log(test4.callPrint());
test3.callPrint()
NamedSuper Hello NamedSuper!
콘솔에 기록 합니다test4.callPrint()
NamedSuper Hello NamedSub!
콘솔에 기록 합니다
Babel REPL에서 실행중인 위의 모든 내용을 참조하십시오 .
test4
여전히 슈퍼 클래스에 있다고 생각하는 것을 볼 수 있습니다 . 이 예에서는 별다른 문제가 아닌 것 같지만 재정의 된 멤버 함수 나 새 멤버 변수를 참조하려고하면 문제가 생길 수 있습니다.