class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
doIt 기능은 “아빠”를 인쇄합니다. “아들”을 인쇄하는 방법이 있습니까?
답변
예. 그러나 변수와 관련하여 변수를 덮어 씁니다 (변수에 새로운 가치를 부여합니다. 함수에 새로운 정의를 부여하는 것은 재정의입니다).Just don't declare the variable but initialize (change) in the constructor or static block.
부모 클래스의 블록에서 사용할 때 값이 반영됩니다.
변수가 정적이면 정적 블록으로 초기화 자체에서 값을 변경하십시오.
class Son extends Dad {
static {
me = 'son';
}
}
또는 생성자에서 변경하십시오.
나중에 블록에서 값을 변경할 수도 있습니다. 그것은 슈퍼 클래스에 반영됩니다
답변
간단히 말해서, 클래스 변수를 재정의하는 방법은 없습니다.
Java에서 클래스 변수를 재정의하지 마십시오. 재정의는 예를 들어 메소드입니다. 숨기는 것은 재정의와 다릅니다.
예를 들어, Son 클래스에서 이름이 ‘me’인 클래스 변수를 선언하여 클래스 이름이 ‘me’인 동일한 수퍼 클래스 Dad에서 상속 된 클래스 변수를 숨 깁니다. 이런 식으로 변수를 숨기는 것은 수퍼 클래스 Dad에서 클래스 변수 ‘me’의 값에 영향을 미치지 않습니다.
질문의 두 번째 부분, “son”을 인쇄하는 방법에 대해서는 생성자를 통해 값을 설정했습니다. 아래 코드는 원래 질문과는 많이 다르지만 다음과 같이 작성합니다.
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void printName() {
System.out.println(name);
}
}
JLS 섹션 8.3-필드 선언 에서 숨기기에 대한 자세한 정보를 제공합니다.
답변
예, printMe()
메소드를 재정의하십시오 .
class Son extends Dad {
public static final String me = "son";
@Override
public void printMe() {
System.out.println(me);
}
}
답변
getter를 작성한 다음 해당 getter를 대체 할 수 있습니다. 재정의하는 변수가 자체의 하위 클래스 인 경우 특히 유용합니다. 수퍼 클래스에 Object
멤버 가 있다고 가정 하지만 하위 클래스에서이 클래스가 더 정의되어 있습니다 Integer
.
class Dad
{
private static final String me = "dad";
protected String getMe() {
return me;
}
public void printMe()
{
System.out.println(getMe());
}
}
class Son extends Dad
{
private static final String me = "son";
@Override
protected String getMe() {
return me;
}
}
public void doIt()
{
new Son().printMe(); //Prints "son"
}
답변
재정의하려는 경우이 정적을 유지 해야하는 유효한 이유가 표시되지 않습니다. 추상화 사용을 제안합니다 (예제 코드 참조). :
public interface Person {
public abstract String getName();
//this will be different for each person, so no need to make it concrete
public abstract void setName(String name);
}
이제 아빠를 추가 할 수 있습니다 :
public class Dad implements Person {
private String name;
public Dad(String name) {
setName(name);
}
@Override
public final String getName() {
return name;
}
@Override
public final void setName(String name) {
this.name = name;
}
}
아들:
public class Son implements Person {
private String name;
public Son(String name) {
setName(name);
}
@Override
public final String getName() {
return name;
}
@Override
public final void setName(String name) {
this.name = name;
}
}
그리고 아빠는 좋은 여자를 만났다 :
public class StepMom implements Person {
private String name;
public StepMom(String name) {
setName(name);
}
@Override
public final String getName() {
return name;
}
@Override
public final void setName(String name) {
this.name = name;
}
}
우리는 가족이있는 것처럼 보이고 세상에 그들의 이름을 알려줍니다.
public class ConsoleGUI {
public static void main(String[] args) {
List<Person> family = new ArrayList<Person>();
family.add(new Son("Tommy"));
family.add(new StepMom("Nancy"));
family.add(new Dad("Dad"));
for (Person person : family) {
//using the getName vs printName lets the caller, in this case the
//ConsoleGUI determine versus being forced to output through the console.
System.out.print(person.getName() + " ");
System.err.print(person.getName() + " ");
JOptionPane.showMessageDialog(null, person.getName());
}
}
}
System.out 출력 : Tommy Nancy Dad
System.err는 위와 동일합니다 (빨간색 글꼴이 있습니다)
JOption 출력 :
Tommy ,
Nancy ,
Dad
답변
이것은 디자인 결함처럼 보입니다.
정적 키워드를 제거하고 예를 들어 생성자에서 변수를 설정하십시오. 이런 식으로 Son은 자신의 생성자에서 변수를 다른 값으로 설정합니다.
답변
클래스 변수는 서브 클래스에만 숨겨지고 재정의되지는 않지만 printMe ()
, 서브 클래스 를 재정의하지 않고 원하는 것을 수행 할 수 있으며 리플렉션은 친구입니다. 아래 코드에서 명확성을 위해 예외 처리를 생략했습니다. 선언 있습니다 me
으로하는 protected
이 서브 클래스에 숨겨져있을 것입니다,이 맥락에서 많은 감각을 갖고있는 것 같다하지 않습니다 …
class Dad
{
static String me = "dad";
public void printMe ()
{
java.lang.reflect.Field field = this.getClass ().getDeclaredField ("me");
System.out.println (field.get (null));
}
}