본문 바로가기

개발일지/Java + Spring

[Java] 상속(extends)의 정의 - overriding, Super()

상속

부모 클래스에서 정의한 변수나 메소드를 자식 클래스에서 자신의 것처럼 사용할 수 있다. extends 예약어를 사용

 

 

package Extends;

public class Parent{
	int age;
	int parentVar = 10;
	
	void parentMethod() {
		System.out.println("parent Method");
	}
}

부모 클래스를 하나 만든다. 여기서 public은 모든 영역에서 접근이 가능한 접근제한자이다. 그리고 인스턴스 멤버 변수 두 개와 메소드 하나가 있다. 

package Extends;

public class Child extends Parent {
		int childVar = 20;
		
		void chilldMethod() {
			System.out.println("child Method");
		}
}

extends로 Parent 클래스를 상속 받는다. 인스턴스 멤버 변수 한 개와 메소드 하나가 있다.

 

package Extends;

public class ExtandsTest1 {
	public static void main(String[] args) {
		Child child = new Child();
		
		System.out.println("child.childVar = " + child.parentVar); //변수
		System.out.println("child.childVar = " + child.childVar);
		
		child.parentMethod(); //메소드
		child.chilldMethod();
	}

}

Main에서 Child 객체를 생성하면 상속 받은 Parent와 Child 두 가지 메소드를 사용할 수 있다. 이곳에서는 캡슐화를 하지 않았지만 실전에서는 캡슐화를 많이 사용한다고 함! 

 


2단계 상속 - 상속 받은 클래스를 또 상속 받는다.

package Extends;

//상위 클래스
class Super{
	int x = 90;
	void superMethod() {
		System.out.println("super Method");
	}
}
//상위 클래스를 상속받는 클래스
class Sub extends Super{
	int y = 10;
	void subMethod() {
		System.out.println("sub method");
	}
}
//상속받은 클래스를 상속받는 클래스
class Subsub extends Sub{
	int z = 20;
	void subsubMethod() {
		System.out.println("subsub method");
	}
}
public class ExtendsTest2 {
	public static void main(String[] args) {
		Subsub ss = new Subsub();
		
		System.out.println("ss.x = " + ss.x);
		System.out.println("ss.y = " + ss.y);
		System.out.println("ss.z = " + ss.z);
		
		ss.superMethod();
		ss.subMethod();
		ss.subsubMethod();
	}

}

상속 받는 법은 똑같다. 마지막으로 상속 받은 Subsub을 Main에서 객체생성 하면 Subsub + sub + super의 메소드와 객체를 모두 사용할 수 있다. 

 


Overriding 오버라이딩

package Overriding;

class OverridingParent{
	void parentMethod() {
		System.out.println("parent Method");
	}
}
class OverridingChild extends OverridingParent{
	void childMethod() {
		System.out.println("Overriding Method");
	}
}
public class OverridingTest1 {
	public static void main(String[] args) {
		OverridingChild oc = new OverridingChild();
		oc.parentMethod();
		oc.childMethod();
	}
}

위에서 사용한 일반 상속이다.

 

package Overriding;

class OverridingParent2{
	int money = 20; //정수형 데이터타입
	void parentMethod() {
		System.out.println("parent Method");
	}
}
class OverridingChild2 extends OverridingParent2{
	String money = "20원"; //문자열 데이터타입으로 바꿈
	void parentMethod() {
		System.out.println("Overriding Method");
	}
}
public class OverridingTest2 {
	public static void main(String[] args) {
		OverridingChild2 oc2 = new OverridingChild2();
		
		System.out.println("oc2.money = " + oc2.money);
       		oc2.parentMethod();
	}
}

 

오버라이딩은 상속 받은 것의 내용을 재정의 하는 것이다. 마찬가지로 상속 받는 법은 같은데 부모 클래스에서 초기화한 값을 자식 클래스에서 변경했다. 멤버변수의 타입을 정수형에서 데이터 타입으로 바꿨고, 메소드 글자도 바꿨다. Main에서 자식클래스로 객체생성을 하고, 출력을 하면 자식 클래스에서 재정의한 20원, Overriding Method가 출력된다.

 

//oc2.money = 30;
oc2.money = "30원";

money 값을 바꾸고 싶다면 데이터 타입을 변경했기 때문에 30이 아니라 "30원"을 입력해야한다. 

 

 


 

 

[Java] 생성자(Constructor), this() 생성자, 초기화 블록

생성자(Constructor) new 연산자에 의해서 객체 생성을 할 때 단 한 번 호출되는 단위(아래에서 9번)이다. 생성자를 이용해서 객체 생성(20, 26, 32)을 하면 Heap 영역에 매 번 새로운 객체가 생성되는 것

practice365.xyz

이곳에서 사용한 this가 연관이 있다..

 

Super

this가 자기 자신 클래스 객체를 가리키는 레퍼런스 변수인 반면, super는 부모 클래스 객체를 가리키는 레퍼런스 변수이다. this()는 자기 자신 클래스 생성자를 호출하고, super()는 부모 클래스 생성자를 호출한다. 

 

package Super;

class Employee1{
	String name; //이름
	String dept; //부서
	int salary; //연봉
	
	String getEmployeeInfo() {
		return "이름 : " + name + ", 부서 : " + dept + ", 연봉 : " + salary;
	}
}
class Salesman1 extends Employee1{
	int commission; //수당
	
	String getEmployeeInfo() {
		return super.getEmployeeInfo() + ", 수당 : " + commission;
		//super부모의.객체를 불러와서 이어서 작성하는 것이다. 
		//super를 정의하지 않으면 기본적으로 this.getEmployeeInfo()가 정의된다.
	}
}

public class SuperTest1 {
	public static void main(String[] args) {
		Salesman1 sm = new Salesman1();
		System.out.println(sm.getEmployeeInfo()); //호출
	}
}


하나하나 모두 써줘도 되지만 중복 코드를 막고, 좀 더 간결하게 만들기 위해서 super로 상속 받은 값을 불러오고 이어서 작성한다. 

	String getEmployeeInfo() {
		return super.getEmployeeInfo() + ", 수당 : " + commission;
	}

 

super부모의 객체를 불러와서 이어서 작성하는 것이다. super를 정의하지 않으면 기본적으로 this.getEmployeeInfo()가 정의된다.

 

package Super;
class Employee2{
	String name;
	String dept;
	int salary;


	public Employee2(String name, String dept, int salary) {
		super();
		this.name = name;
		this.dept = dept;
		this.salary = salary;
	}
	
	String getEmployeeInfo() {
		return "이름 : " + name + ", 부서 : " + dept + ", 연봉 : " + salary;
	}	
}
class Salesman2 extends Employee2{
	int commission;
	public Salesman2(String name, String dept, int salary, int commission) {
		//super()
		super(name, dept, salary); //부모에게 받은 변수 세개
		this.commission = commission; //18 Line
	}

	/*String getEmployeeInfo(){
	  return "이름 : " + name + ", 부서 : " + dept + ", 연봉 : " + salary + ", 수당 : " + commission;
	  }
	 */ 
	String getEmployeeInfo() {
		return super.getEmployeeInfo() + ", 수당 : " + commission;
	}
}
public class SuperConstructorTest{
	public static void main(String[] args) {
		Salesman2 sales2 = new Salesman2("오정원", "영업부", 100000000, 70000000);
		System.out.println(sales2.getEmployeeInfo());
	}	
}
//p220

 

위에서 쳤던 코드와 다르 게 super() 라는 게 눈에 띈다. 위에서는 변수 값을 할당한 부분이 없는지라 데이터 타입의 기본값들이 출력된다. 그런데 여기서는 Main에서 할당값(인자)이 있으니 super()를 사용해야한다. 

 

	public Employee2(String name, String dept, int salary) {
		super();
		this.name = name;
		this.dept = dept;
		this.salary = salary;
	}

 

인자가 건너와 파라미터 값이 왔다. 그것을 나의 변수에 넣어주어야한다. 그 과정에서 시작 전에 super()를 넣어주고 시작을 해야한다. 왜? 라고 하면 답하기 곤란한 게 규약이다.. 위에서 지정한 내 클래스의 멤버변수를 가리키는 게 this.name = name; 그리고 파라미터 값은 오른쪽 name이 된다. 

 

	public Salesman2(String name, String dept, int salary, int commission) {
		//super()
		super(name, dept, salary); //부모에게 받은 변수 세개
		this.commission = commission; //18 Line
	}

 

Employee2에서 부모 클래스에 인자가 있을 때 super(name, dept, salary)를 만들어주지 않는다면 위에 있는 라인super() 이것이 자동으로 호출되어 컴파일 오류가 발생한다. 부모클래스에는 빈 생성자가 없기 때문에 넣어줘야하고, 안에 들어가는 값이 같아야한다.

 

 


package Super;

class Employee3{
	String name = "홍길동";
}
class Salesman3 extends Employee3{
	String name = "오정원";
	
	String getNameLocal() {
		String name = "이만수";
		return name;
	}
	String getNameThis() {
		String name = "이만수";
		return this.name;
	}
	String getNameSuper() {
		String name = "이만수";
		return super.name;
	}
}

public class SuperVariableTest {
	public static void main(String[] args) {
		Salesman3 sm = new Salesman3();
		System.out.println("Local.name = " + sm.getNameLocal());
		System.out.println("This.name = " + sm.getNameThis());
		System.out.println("Super.name = " + sm.getNameSuper());
	}
}
Local.name = 이만수
This.name = 오정원
Super.name = 홍길동

 

return name - 로컬변수에서 정의한 name 변수값을 반환

return this.name - 자기 자신 클래스에서 정의한 name 변수값을 반환

return super.name - 부모 클래스에서 정의한 name 변수값을 반환