Programing

서브 클래스는 개인 필드를 상속합니까?

lottogame 2020. 4. 16. 08:11
반응형

서브 클래스는 개인 필드를 상속합니까?


이것은 인터뷰 질문입니다.

서브 클래스는 개인 필드를 상속합니까?

"일반 OOP 방식"을 사용하여 액세스 할 수 없으므로 "아니오"라고 대답했습니다. 그러나 면접관은 이러한 필드를 간접적으로 또는 리플렉션을 사용하여 액세스 할 수 있으며 여전히 객체에 존재하기 때문에 상속 된 것으로 생각합니다.

돌아온 후 javadoc 에서 다음 인용문을 찾았습니다 .

수퍼 클래스의 개인 회원

서브 클래스는 부모 클래스의 private 멤버를 상속하지 않습니다.

면접관의 의견에 대한 논쟁이 있습니까?


여기에있는 질문 / 답변의 혼란은 대부분 상속의 정의를 둘러 쌉니다.

@DigitalRoss가 설명했듯이 서브 클래스 객체 는 반드시 슈퍼 클래스의 개인 필드를 포함해야합니다. 그가 말했듯이, 개인 회원에 대한 액세스 권한이 없다고해서 해당 회원이 없다는 의미는 아닙니다.

하나. 이것은 클래스에 대한 상속 개념과 다릅니다. 시맨틱에 대한 의문이있는 Java 세계의 경우와 마찬가지로 중재자는 Java 언어 사양 (현재 3 판)입니다.

JLS가 명시한대로 ( https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2 ) :

private로 선언 된 클래스의 멤버는 해당 클래스의 서브 클래스에 의해 상속되지 않습니다. protected 또는 public으로 선언 된 클래스의 멤버 만 클래스가 선언 된 패키지가 아닌 패키지에 선언 된 서브 클래스에 의해 상속됩니다.

이것은 면접관이 제기 한 정확한 질문을 다룬다 : "하위 클래스는 개인 필드를 상속한다". (나에 의해 추가 된 강조)

대답은 아니요입니다. 그렇지 않습니다. 서브 클래스의 오브젝트는 수퍼 클래스의 개인 필드를 포함합니다. 서브 클래스 자체에는 수퍼 클래스의 개인 필드가 없습니다.

그것은 pedantic 자연의 의미론인가? 예. 유용한 인터뷰 질문입니까? 아마 아닙니다. 그러나 JLS는 Java 세계에 대한 정의를 확립하며 (이 경우) 명확하게 수행합니다.

편집 (Bjarne Stroustrup에서 병렬 인용문을 제거했습니다 .Java와 c ++의 차이점으로 인해 혼란을 더할 수 있습니다. JLS에 대한 답변을 드리겠습니다 :)


그것은 거기있는 동안 것을 깨닫게하는 것이 중요 하다 두 개의 클래스를 하나의 객체가있다.

물론, 그것은 개인 필드를 물려 받았습니다. 그것들은 아마도 적절한 객체 기능에 필수적이며, 부모 클래스의 객체는 파생 클래스의 객체가 아니지만 파생 클래스의 인스턴스는 대부분 분명히 부모 클래스의 인스턴스입니다. 모든 분야가 없으면 그렇게 될 수 없었습니다.

아니요, 직접 액세스 할 수 없습니다. 예, 그들은 상속받습니다. 그들은 해야 합니다.

좋은 질문입니다!


최신 정보:

Err, "아니오"

글쎄, 우리 모두가 무언가를 배운 것 같아. JLS 는 정확한 "상속되지 않은"문구를 시작 했기 때문에 "no"라고 대답하는 것이 맞습니다 . 서브 클래스는 개인 필드에 액세스하거나 개인 필드를 수정할 수 없으므로 다시 말해 상속되지 않습니다. 그러나 실제로 하나의 객체 가 있으며 실제로 개인 필드를 포함 하므로 누군가가 JLS 및 자습서 문구를 잘못 입력하면 OOP, Java 객체 및 실제로 발생하는 상황을 이해하기가 매우 어려울 것입니다.

업데이트 업데이트 :

여기서 논란은 근본적인 모호성을 포함합니다. 정확히 무엇을 논의하고 있습니까? 객체? 아니면 수업 자체 에 대해 어떤 의미로 이야기 하고 있습니까? 객체와 반대로 클래스를 설명 할 때 많은 위도가 허용됩니다. 서브 클래스가 없습니다 상속 private 필드를 않지만, 그래서 서브 클래스의 인스턴스 인 객체는 확실하지 가 포함 전용 필드.


아니요. 개인 필드는 상속되지 않습니다 . 이것이 바로 Protected 가 발명 이유 입니다. 의도적으로 설계된 것입니다. 이것이 보호 된 수정 자의 존재를 정당화했다고 생각합니다.


이제 상황에 왔습니다. 상속 된 의미-파생 클래스에서 만든 객체에있는 경우? 그렇습니다.

당신이 의미하는 경우 파생 클래스에 유용 할 수 있습니다. 음 ... 아니.

이제 함수형 프로그래밍에 관해서는 수퍼 클래스의 전용 필드가 하위 클래스에 대해 의미있는 방식으로 상속되지 않습니다 . 서브 클래스의 경우, 수퍼 클래스의 개인 필드는 다른 클래스의 개인 필드와 동일합니다.

기능적으로는 상속되지 않습니다. 그러나 이상적으로그렇습니다 .


자, Java 자습서를 살펴보면 다음과 같이 인용합니다.

수퍼 클래스의 개인 회원

서브 클래스는 부모 클래스의 private 멤버를 상속하지 않습니다. 그러나 수퍼 클래스가 개인 필드에 액세스하기위한 공용 또는 보호 된 메소드를 가지고 있으면 서브 클래스에서도 사용할 수 있습니다.

참조 : http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

필드가 있다는 것에 동의합니다. 그러나 서브 클래스는 해당 개인 필드에 대한 권한을 갖지 않습니다. 서브 클래스에서 개인 필드는 다른 클래스의 개인 필드와 동일합니다.

나는 그것이 순수한 관점의 문제라고 생각합니다. 당신은 어느 쪽의 주장이든 틀릴 수 있습니다. 양방향으로 정당화하는 것이 좋습니다.

 


"상속"의 정의에 따라 다릅니다. 서브 클래스는 여전히 메모리에 필드를 가지고 있습니까? 명확히. 직접 액세스 할 수 있습니까? 아닙니다. 정의의 미묘한 부분 일뿐입니다. 요점은 실제로 무슨 일이 일어나고 있는지 이해하는 것입니다.


코드로 개념을 설명하겠습니다. 서브 클래스는 실제로 수퍼 클래스의 전용 변수를 상속 합니다. 유일한 문제점은 수퍼 클래스의 개인 변수에 대해 공용 게터 및 세터를 제공하지 않으면 하위 오브젝트에 액세스 할 수 없다는 것 입니다.

패키지 덤프의 두 클래스를 고려하십시오. 어린이는 부모를 연장합니다.

올바르게 기억하면 메모리의 자식 객체는 두 영역으로 구성됩니다. 하나는 부모 부분이고 다른 하나는 자식 부분입니다. 자녀는 부모의 공개 메소드를 통해서만 부모 코드의 개인 섹션에 액세스 할 수 있습니다.

이런 식으로 생각하십시오. 보랏의 아버지 볼톡은 10 만 달러의 금고를 가지고있다. 그는 "개인"변수 금고를 공유하고 싶지 않습니다. 따라서 그는 금고 열쇠를 제공하지 않습니다. 보랏은 금고를 물려받습니다. 그러나 그가 열 수조차 없다면 무엇이 좋을까요? 그의 아빠 만 열쇠를 제공했다면.

부모의 -

package Dump;

public class Parent {

    private String reallyHidden;
    private String notReallyHidden;

    public String getNotReallyHidden() {
        return notReallyHidden;
    }

    public void setNotReallyHidden(String notReallyHidden) {
        this.notReallyHidden = notReallyHidden;
    }

}//Parent

아이 -

package Dump;

public class Child extends Parent {

    private String childOnly;

    public String getChildOnly() {
        return childOnly;
    }

    public void setChildOnly(String childOnly) {
        this.childOnly = childOnly;
    }

    public static void main(String [] args){

        System.out.println("Testing...");
        Child c1 = new Child();
        c1.setChildOnly("childOnly");
        c1.setNotReallyHidden("notReallyHidden");

        //Attempting to access parent's reallyHidden
            c1.reallyHidden;//Does not even compile

    }//main

}//Child

아니요. 상속하지 않습니다.

다른 클래스가 간접적으로 사용할 수 있다는 사실은 상속에 대해 아무것도 말하지 않고 캡슐화에 대해 말합니다.

예를 들어 :

class Some { 
   private int count; 
   public void increment() { 
      count++;
   }
   public String toString() { 
       return Integer.toString( count );
   }
}

class UseIt { 
    void useIt() { 
        Some s = new Some();
        s.increment();
        s.increment();
        s.increment();
        int v = Integer.parseInt( s.toString() );
        // hey, can you say you inherit it?
     }
}

반사를 통해 count내부 의 가치를 얻을 수도 있습니다 UseIt. 그것은 당신이 그것을 상속한다는 의미는 아닙니다.

최신 정보

값은 있지만 서브 클래스에 의해 상속되지 않습니다.

예를 들어 다음과 같이 정의 된 서브 클래스 :

class SomeOther extends Some { 
    private int count = 1000;
    @Override
    public void increment() { 
        super.increment();
        count *= 10000;
    }
}

class UseIt { 
    public static void main( String ... args ) { 
        s = new SomeOther();
        s.increment();
        s.increment();
        s.increment();
        v = Integer.parseInt( s.toString() );
        // what is the value of v?           
     }
}

이것은 첫 번째 예와 정확히 같은 상황입니다. 속성 count은 숨겨져 서브 클래스에 의해 상속 되지 않습니다 . 여전히 DigitalRoss가 지적했듯이 그 가치는 있지만 상속 수단이 아닙니다.

이렇게하세요 당신의 아버지가 부유하고 당신에게 신용 카드를 주더라도, 당신은 여전히 ​​그의 돈으로 물건을 살 수 있지만 , 그 돈을 모두 상속 받았다는 것을 의미 하지는 않습니까?

다른 업데이트

속성이 왜 존재하는지 아는 것은 매우 흥미 롭습니다 .

솔직히 설명 할 정확한 용어는 없지만 JVM이고 "상속되지 않은"상위 정의도로드하는 방식입니다.

실제로 부모를 변경할 수 있으며 하위 클래스는 여전히 작동합니다.

예를 들면 다음과 같습니다.

//A.java
class A {
   private int i;
   public String toString() { return ""+ i; }
}
// B.java
class B extends A {}
// Main.java
class Main {
   public static void main( String [] args ) {
      System.out.println( new B().toString() );
    }
}
// Compile all the files
javac A.java B.java Main.java
// Run Main
java Main
// Outout is 0 as expected as B is using the A 'toString' definition
0

// Change A.java
class A {
   public String toString() {
      return "Nothing here";
   }
}
// Recompile ONLY A.java
javac A.java
java Main
// B wasn't modified and yet it shows a different behaviour, this is not due to 
// inheritance but the way Java loads the class
Output: Nothing here

정확한 용어는 여기에서 찾을 수 있습니다 . JavaTM Virtual Machine Specification


면접관의 질문에 대한 나의 대답은- 개인 멤버는 서브 클래스에서 상속되지 않지만 공개 getter 또는 setter 메소드 또는 원래 클래스의 적절한 메소드를 통해서만 서브 클래스 또는 서브 클래스의 객체에 액세스 할 수 있다는 것입니다. 일반적인 관행은 멤버를 비공개로 유지하고 공개적인 getter 및 setter 메소드를 사용하여 멤버에 액세스하는 것입니다. 그렇다면 다루는 개인 멤버가 객체에 제공되지 않을 때 getter 및 setter 메소드 만 상속하는 요점은 무엇입니까? 여기서 '상 속됨'은 단순히 서브 클래스에서 새로 도입 된 메소드를 통해 서브 클래스에서 직접 사용할 수 있음을 의미합니다.

아래 파일을 ParentClass.java로 저장하고 직접 시도하십시오->

public class ParentClass {
  private int x;

  public int getX() {
    return x;
  }

  public void setX(int x) {
    this.x = x;
  }
}

class SubClass extends ParentClass {
  private int y;

  public int getY() {
    return y;
  }

  public void setY(int y) {
    this.y = y;
  }

  public void setXofParent(int x) {
    setX(x); 
  }
}

class Main {
  public static void main(String[] args) {
    SubClass s = new SubClass();
    s.setX(10);
    s.setY(12);
    System.out.println("X is :"+s.getX());
    System.out.println("Y is :"+s.getY());
    s.setXofParent(13);
    System.out.println("Now X is :"+s.getX());
  }
}

Output:
X is :10
Y is :12
Now X is :13

SubClass의 메소드에서 ParentClass의 전용 변수 x를 사용하려고하면 수정을 위해 직접 액세스 할 수 없습니다 (상속되지 않음). 그러나 x는 setXofParent () 메소드에서와 같이 원래 클래스의 setX () 메소드를 통해 SubClass에서 수정 될 수 있으며 setX () 메소드 또는 setXofParent () 메소드를 사용하여 ChildClass 객체를 사용하여 최종적으로 setX ()를 호출하여 수정할 수 있습니다. 여기에서 setX ()와 getX ()는 ParentClass의 private 멤버 x에 대한 일종의 게이트입니다.

또 다른 간단한 예는 Clock 수퍼 클래스에 개인 구성원으로 시간과 분이 있고 공용으로 적절한 getter 및 setter 메소드가 있다는 것입니다. 그런 다음 DigitalClock이 Clock의 하위 클래스로 제공됩니다. 여기서 DigitalClock의 객체에 시간과 분이 포함되어 있지 않으면 문제가 해결됩니다.


좋아, 이것은 내가 많이 연구 한 매우 흥미로운 문제이며, 수퍼 클래스의 개인 멤버는 서브 클래스의 오브젝트에서 실제로 사용 가능하지만 액세스 할 수는 없다는 결론에 도달했다. 이를 증명하기 위해 여기에 부모 클래스와 자식 클래스가있는 샘플 코드가 있으며 txt 파일에 자식 클래스 객체를 쓰고 파일에서 'bhavesh'라는 개인 멤버를 읽고 있으므로 실제로는 자식에서 사용할 수 있음을 증명합니다 액세스 한정자로 인해 클래스에 액세스 할 수 없습니다.

import java.io.Serializable;
public class ParentClass implements Serializable {
public ParentClass() {

}

public int a=32131,b,c;

private int bhavesh=5555,rr,weq,refw;
}

import java.io.*;
import java.io.Serializable;
public class ChildClass extends ParentClass{
public ChildClass() {
super();
}

public static void main(String[] args) {
ChildClass childObj = new ChildClass();
ObjectOutputStream oos;
try {
        oos = new ObjectOutputStream(new FileOutputStream("C:\\MyData1.txt"));
        oos.writeObject(childObj); //Writing child class object and not parent class object
        System.out.println("Writing complete !");
    } catch (IOException e) {
    }


}
}

MyData1.txt를 열고 이름이 'bhavesh'인 개인 구성원을 검색하십시오. 당신의 생각을 알려주세요.


서브 클래스는 이러한 필드가 서브 클래스의 내부 작업에 철학적으로 사용된다는 점에서 개인 필드를 상속하는 것으로 보입니다. 생성자에서 서브 클래스는 수퍼 클래스 생성자를 호출합니다. 수퍼 클래스 개인 필드는 수퍼 클래스 생성자가 생성자에서 이러한 필드를 초기화 한 경우 수퍼 클래스 생성자를 호출하는 서브 클래스에 의해 상속됩니다. 그것은 단지 예일뿐입니다. 그러나 물론 접근 자 메소드가 없으면 서브 클래스는 수퍼 클래스 개인 필드에 액세스 할 수 없습니다 (전화를 재설정하기 위해 배터리를 꺼내기 위해 iPhone의 후면 패널을 팝업 할 수는 없지만 배터리는 여전히 남아 있습니다).

PS 상속의 많은 정의 중 하나 : "상속-파생 클래스가 기본 클래스의 기능을 확장하고 모든 STATE (강조는 내 것)과 동작을 상속 할 수있는 프로그래밍 기술입니다."

서브 클래스에서 액세스 할 수없는 경우에도 개인 필드는 수퍼 클래스의 상속 된 상태입니다.


Java에 대한 Java의 메모리 레이아웃 상속

여기에 이미지 설명을 입력하십시오

패딩 비트 / 정렬 및 VTABLE에 객체 클래스 포함은 고려되지 않습니다. 따라서 서브 클래스의 객체는 수퍼 클래스의 프라이빗 멤버를위한 장소를 갖습니다. 그러나 서브 클래스의 객체에서 액세스 할 수 없습니다 ...


아니요 , 개인 필드는 상속되지 않습니다. 유일한 이유는 서브 클래스가 직접 서브 클래스에 액세스 할 수 없기 때문입니다 .


나는 대답이 전적으로 질문에 달려 있다고 믿는다. 만약 질문이

하위 클래스에서 수퍼 클래스의 개인 필드에 직접 액세스 할 수 있습니까 ?

그런 다음 대답은 아니요 이며 액세스 지정자 세부 정보 를 살펴보면 개인 구성원은 클래스 자체 내에서만 액세스 할 수 있습니다.

그러나 질문이

하위 클래스에서 수퍼 클래스의 개인 필드에 액세스 할 수 있습니까?

즉, 개인 회원에게 액세스하기 위해 무엇을 할 것인지는 중요하지 않습니다. 이 경우 수퍼 클래스에서 공개 메소드를 작성할 수 있으며 개인 멤버에게 액세스 할 수 있습니다. 따라서이 경우 개인 멤버에 액세스하기 위해 하나의 인터페이스 / 브리지를 작성합니다.

C ++과 같은 다른 OOP 언어 friend function에는 다른 클래스의 개인 멤버에 액세스 할 수 있는 개념이 있습니다.


수퍼 클래스가 상속 될 때 수퍼 클래스의 프라이빗 멤버는 실제로 서브 클래스의 프라이빗 멤버가되어 더 이상 상속 받거나 서브 클래스의 객체에 접근 할 수 없다고 간단히 말할 수 있습니다.


Java의 개인 필드 상속 되었다고 대답해야합니다 . 보여 줄게

public class Foo {

    private int x; // This is the private field.

    public Foo() {
        x = 0; // Sets int x to 0.
    }

    //The following methods are declared "final" so that they can't be overridden.
    public final void update() { x++; } // Increments x by 1.
    public final int getX() { return x; } // Returns the x value.

}


public class Bar extends Foo {

    public Bar() {

        super(); // Because this extends a class with a constructor, it is required to run before anything else.

        update(); //Runs the inherited update() method twice
        update();
        System.out.println(getX()); // Prints the inherited "x" int.

    }

}

프로그램에서 실행 Bar bar = new Bar();하면 출력 상자에 항상 숫자 "2"가 표시됩니다. 정수 "x"는 update()메소드로 캡슐화 getX()되므로 정수가 상속되었음을 증명할 수 있습니다.

혼란스러운 점은 정수 "x"에 직접 액세스 할 수 없기 때문에 사람들은이를 상속받지 않는다고 주장합니다. 그러나 클래스 또는 필드의 모든 정적이 아닌 것은 상속됩니다.


개인 클래스 멤버 또는 생성자는 멤버 또는 생성자 의 선언을 포함하는 최상위 클래스 ( §7.6 ) 본문 내에서만 액세스 할 수 있습니다 . 서브 클래스에 의해 상속되지 않습니다. https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6


서브 클래스는 부모 클래스의 private 멤버를 상속하지 않습니다. 그러나 수퍼 클래스가 개인 필드에 액세스하기위한 공용 또는 보호 된 메소드를 가지고 있으면 서브 클래스에서도 사용할 수 있습니다.


개인 구성원 (상태 및 동작)이 상속됩니다. 그것들은 클래스에 의해 인스턴스화되는 객체의 행동과 크기에 영향을 줄 수 있습니다. 그것들은 이용 가능하거나 구현 자들에 의해 가정 될 수있는 모든 침입 차단 메커니즘을 통해 서브 클래스들에게 잘 보여진다는 것은 말할 것도 없습니다.

상속에는 "사실상"정의가 있지만 "가시"라는 대답으로 가정되는 "가시성"측면과는 관련이 없습니다.

따라서 외교적 일 필요는 없습니다. 이 시점에서 JLS는 잘못되었습니다.

그들이 "상속"되지 않았다는 가정은 안전하지 않으며 위험합니다.

따라서 (부분적으로) 상충되는 두 가지 정의 (반복하지 않을 것) 중 지켜야 할 유일한 것은 더 안전하거나 안전한 것입니다.

참고 URL : https://stackoverflow.com/questions/4716040/do-subclasses-inherit-private-fields

반응형