[java] 추상 필드가 아닌 이유는 무엇입니까?

Java 클래스는 추상 메서드를 가질 수있는 것처럼 추상 필드를 가질 수없는 이유는 무엇입니까?

예 : 동일한 추상 기본 클래스를 확장하는 두 개의 클래스가 있습니다. 이 두 클래스는 각각 오류 메시지 인 String 상수를 제외하고 동일한 메서드를 포함합니다. 필드가 추상 일 수 있다면이 상수 추상을 만들고 메서드를 기본 클래스로 끌어 올 수 있습니다. 대신 getErrMsg()이 경우 호출되는 추상 메서드를 만들어야합니다. 이 메서드는 String을 반환하고 두 파생 클래스에서이 메서드를 재정의 한 다음 메서드 (이제 추상 메서드를 호출 함)를 가져올 수 있습니다.

필드를 추상적으로 시작할 수없는 이유는 무엇입니까? Java가이를 허용하도록 설계되었을 수 있습니까?



답변

생성자 (unested 코드)에서 초기화 된 추상 클래스의 최종 필드를 사용하여 설명한 작업을 수행 할 수 있습니다.

abstract class Base {

    final String errMsg;

    Base(String msg) {
        errMsg = msg;
    }

    abstract String doSomething();
}

class Sub extends Base {

    Sub() {
        super("Sub message");
    }

    String doSomething() {

        return errMsg + " from something";
    }
}

자식 클래스가 슈퍼 생성자를 통해 최종 초기화를 “잊으면”컴파일러는 추상 메서드가 구현되지 않은 것처럼 경고를 표시 합니다.


답변

나는 그것에 대해 아무 의미가 없다. 함수를 추상 클래스로 이동하고 일부 보호 된 필드를 재정의 할 수 있습니다. 이것이 상수와 함께 작동하는지 모르겠지만 효과는 동일합니다.

public abstract class Abstract {
    protected String errorMsg = "";

    public String getErrMsg() {
        return this.errorMsg;
    }
}

public class Foo extends Abstract {
    public Foo() {
       this.errorMsg = "Foo";
    }

}

public class Bar extends Abstract {
    public Bar() {
       this.errorMsg = "Bar";
    }
}

그래서 당신의 요점은 errorMsg하위 클래스에서 구현 / 재정의 / 무엇이든 강제하고 싶다는 것입니다 . 나는 당신이 기본 클래스에 메소드를 갖고 싶었고 그 필드를 다루는 방법을 몰랐다고 생각했습니다.


답변

분명히 이것을 허용하도록 설계되었을 있지만 내부적으로는 여전히 동적 디스패치를 ​​수행해야하고 따라서 메서드 호출이 필요합니다. 자바의 디자인 (적어도 초기에는)은 어느 정도 미니멀리스트가 되려는 시도였습니다. 즉, 디자이너는 이미 언어에있는 다른 기능으로 쉽게 시뮬레이션 할 수 있다면 새로운 기능을 추가하지 않으려 고했습니다.


답변

제목을 읽으면서 추상 인스턴스 멤버를 언급하고 있다고 생각했습니다. 그리고 나는 그것들이 많이 사용되는 것을 보지 못했습니다. 그러나 추상 정적 멤버는 완전히 다른 문제입니다.

나는 종종 자바에서 다음과 같은 메소드를 선언 할 수 있기를 바랐다.

public abstract class MyClass {

    public static abstract MyClass createInstance();

    // more stuff...

}

기본적으로 부모 클래스의 구체적인 구현이 특정 서명이있는 정적 팩토리 메서드를 제공한다고 주장하고 싶습니다. 이렇게하면 구체적인 클래스에 대한 참조를 얻을 수 있고 Class.forName()내가 선택한 규칙에 따라 구성 할 수 있습니다.


답변

또 다른 옵션은 기본 클래스에서 필드를 공용 (원하는 경우 최종)으로 정의한 다음 현재 사용중인 하위 클래스에 따라 기본 클래스의 생성자에서 해당 필드를 초기화하는 것입니다. 순환 종속성을 도입한다는 점에서 약간 그늘진 것입니다. 그러나 적어도 변경 될 수있는 종속성은 아닙니다. 즉, 하위 클래스는 존재하거나 존재하지 않지만 하위 클래스의 메서드 또는 필드는의 값에 영향을 줄 수 없습니다 field.

public abstract class Base {
  public final int field;
  public Base() {
    if (this instanceof SubClassOne) {
      field = 1;
    } else if (this instanceof SubClassTwo) {
      field = 2;
    } else {
      // assertion, thrown exception, set to -1, whatever you want to do 
      // to trigger an error
      field = -1;
    }
  }
}


답변