JAVA/Bootcamp 자바

부모, 자식, 상속, protected, extends

whyHbr 2024. 2. 27. 17:44
728x90
반응형

부모: 상위 클래스, 슈퍼클래스,

자식 : 서브클래스, 파생클래스

 

부모가 자식에게 상속을 해줬다 -> 언제든 쓸 수 있다. 하지만 부모 소유이다. 

 

 상속

클래스를 계층화 하는 것을 상속이라고 한다. 

 

상속하는 이유?

- 객체를 설계하다 보면 비슷한 클래스들끼리 중복요소가 생긴다.

 

ex)책이라는 클래스에 꼭 들어가야 하는 것(저자, 제목, 출판사, 페이지 )을 가진 부모 클래스가 이것을 자식에게 상속해주면 자식은 자유롭게 쓸 수 있다.

 

상속시 자식은 extends 라는 키워를 사용한다.

자바는 단일상속만을 지원한다. 부모를 한 명으로 두고 사용하는 것을 단일상속이라고 한다.

 

상속에서 private를 사용하면 상속의 의미가 퇴색된다. private인데 상속을 어떻게 해

부모의 기억공간을 자식에게 상속하고 싶다면 private을 쓰면 안된다.

그래서 자식만큼은 접근을 가능케 하는 protected를 사용한다.

 

public은 자식 말고 다른 것도 접근 가능하다. private은 자식마저 접근 할 수 없다. protected는 자식만 접근 할 수 있다/ 상속관계서 접근을 허용한다.

 

public class RempVO extends Employee {
    public RempVO(){
        super();
    }

 

extends기준으로 오른쪽이 부모Employee 이고, 왼쪽이 자식RempVO이다

 

super(); 는 상위 클래스를 가리킬 때 사용한다. . 

명시하지 않으면 컴파일러가 자동으로 추가해준다.

자식 생성 전 부모가 먼저 생성되어 있어야 하는데, super가 호출되면 자식이 아니라 부모 먼저 메모리에 생성된다.

super에 의해 new Employee()가 호출된다.

 

이렇게 생성 된 후, 부모와 자식이 붙어있는 형태로 메모리에 생성된다.

 

먼저 Employee가 생성되고 RempVO가 부모까지 확장해 부모까지 쓸 수 있게된다.

RempVO는 본인 뿐 만 아니라 부모인 Employee 공간까지 접근 할 수 있다.

 

//사원이라는 데이터 클래스를 담기위한 VO
public class Employee { //extends Object 이게 생략되어있음
   
private String name;
    private
String empDate;
    private
String dept;
    private boolean
marriage;

    public
Employee(){
       
super(); //상위 클래스의 생성자를 호춯 //object부터 생성
   
}
}

부모 Employee는 어느 사원에게나 있을 법한 상태변수를 가지고 있다.

 

//일반사원vo
public class RempVO extends  Employee{
   
public RempVO(){
       
super();
   
}
}

그것을 자식이 extends에 의해 상속받고, super에 의해 부모 메모리 생성 후 자식을 생성한다. (super()는 자동 생성되기 때문에 생략해도 괜찮다.)

 

public class EmployeeTest {
   
public static void main(String[] args) {
       
//일반사원 명의 객체 생성 , 데이터 저장 출력
       
RempVO vo = new RempVO();// 상속 받은 상태
       
vo.name="";

   
}
}

부모가 private이라 상속받은 변수를 사용 할 수 없다..

이럴 때  protected를 사용한다. protected는 같은 패키지 안에서만 사용할 수 있다

집떠나면 남..

 

public class Employee { //extends Object 이게 생략되어있음
   
protected String name;
    protected int
age;
    protected
String dept;
    protected boolean
marriage;

부모의 상태변수를 protected로 바꾼다.

 

public class EmployeeTest {
   
public static void main(String[] args) {
       
//일반사원 명의 객체 생성 , 데이터 저장 출력
       
RempVO vo = new RempVO();// 상속 받은 상태
       
vo.name="rempvoname";
       
vo.age =10;
       
vo.dept ="HR";
       
vo.marriage =false;
       
   
}
}

vo.name, vo.age.. 이렇게 써주면 된다.

부모와 자식이 같은 패키지 안에 있어야 가능한것이다.

 

부모 클래스에 toString() 추가 후 vo.toString()해서 사용해보자

 

 

하지만

자식이 부모의 데이터 공간에 유효하지 않은 데이터를 넣을 수도 있다.

ex_ vo.age =234987; 해도 문제가 없다

RempVO의this는 부모의 상태변수를 가리킨다. 그래서 매개변수로 값을 받아 부모의 상태정보에 값을 넣는다. 이게 일종의 초기화가 될 수 있다

하지만 여전히 자식이 부모 상태에접근해 데이터 넣기가 가능하다 -> 정보은닉이 아니다. 이상한 데이터 값을 넣어도 막지 못한다. 

 

생성자에 의해 초기화를 해보자면

public RempVO(String name, int age,String dept, boolean marriage ){
       
this.name= name;
        this
.age = age;
        this
.dept =dept;
        this
.marriage =marriage;
       
//자식이 부모의 기억공간을 초기화 중이다.
  
}
}

자식 클래스에 생성자를 만들어 부모 기억공간을 초기화하는 중이다.

 

public class EmployeeInitTest {
   
public static void main(String[] args) {
        RempVO vo =
new RempVO("NAME",333,"DEV",true);
       
System.out.println(vo.toString());
   
}
}

 

초기화는 자기 자신이 하는 경우가 바람직하다. 상태변수의 접근 제어자도 private이 맞는 것이다

그럼 어떻게 값을 넣나? 

-> 자식이 값을 받고 그 값을 부모에게 넘겨줘 대신 초기화 해주는 것이 바람직하다.

 

하지만 접근 제어자를 private으로 하면 this는 전부 에러가 난다.

 

상속관계에서의 초기화

부모한테 초기화 부탁을 해보자.

 

일단 부모 상태 정보 멤버변수의 접근제어를  private으로 변경한다 - 자식이 super("name",1); 사용 -부모의 생성자에서 초기화

 

 

부모 클래스에 Employee 생성자를 하나 더 생성한다.

public Employee(String name, int age, String dept, boolean marriage) {
   
this.name = name;
    this
.age = age;
    this
.dept = dept;
    this
.marriage = marriage;
}

이렇게 부모가 값을 받아 저장한다. 

public RempVO(String name, int age,String dept, boolean marriage ){
    super(name,age,dept,marriage);
    //부모의 생성자 호출하고 값을 전달
}

자식은 super();을 사용해 호출하고 전달한다. 

 

public class EmployeeTest {
   
public static void main(String[] args) {
       
//일반사원 명의 객체 생성 , 데이터 저장 출력
       
RempVO vo = new RempVO("whffu",22,"dev",true);// 상속 받은 상태

       
System.out.println(vo); //toString 생략
   
}
}

EmployeeTest서 값을 넣을 때도 vo.name -"name"; 이 아니라

객체 생성하면서 바로 넣는다 RempVo vo = new rempVo("name", 3);

728x90