[JAVA] 클래스 상속

kbannie·2022년 10월 11일
0

JAVA

목록 보기
5/8
post-thumbnail

📌 클래스 상속

클래스 상속?

포괄적인 속성/행위를 갖는 클래스로 구현을 하고 싶으면서 독립적인 클래스로 구현하고 싶을 때 클래스 상속을 해줍니다. 즉, 개별적인 클래스를 정의하면서 (1) 반복적인 코드는 최소화 (2) 비슷한 행위는 공통의 인터페이스 사용 (3) 객체를 명확히 구분하고 싶을 때 클래스 상속을 통해 이를 해결할 수 있습니다.

상속의 이점

  • 코드의 재사용이 가능합니다.
    • 검증된 코드의 재사용으로 오류를 최소화합니다.
    • 소스 코드의 관리와 유지보수가 용이합니다.
    • 개발 시간을 단축해줍니다.
  • ⭐ 연관된 일련의 클래스에 대한 공통 규약을 정의합니다.
    • 클래스 객체 간의 동작을 통일시켜 간결성을 제공해줍니다.

공통점을 갖고 있지만 서로 다른 클래스들을 상속을 기반으로 설계하여 각 객체들간의 동작이나 특성을 통일성있게 유지하며 소스코드와 유지 보수를 쉽게 이룰 수 있습니다.

IS-A 관계

IS-A(~중의 하나) 관계가 성립할 때 상속을 기반으로 표현할 수 있습니다.

📌 JAVA 클래스 상속

JAVA 클래스 상속 특징

  • JAVA의 모든 클래스는 Object 클래스로부터 파생됩니다.
  • 단일 상속만 제공됩니다.
  • private 멤버일 경우 상속은 되나 직접 참조는 불가능합니다. access 메서드(getter, setter)를 이용하면 접근할 수 있습니다.
  • 하위 클래스의 생성자 첫 줄에서 상위 클래스의 생성자를 명시적으로 호출합니다.

super 클래스 vs sub 클래스

  • super 클래스 : 상위클래스로 자신의 멤버들을 상속해주는 클래스입니다.
  • sub 클래스 : 하위클래스로 super 클래스로부터 멤버들을 상속 받는 클래스입니다.

protected, private 접근 지정자

Person 클래스가 super 클래스이며 UnivStudent가 sub 클래스입니다.

보통 Person 클래스의 멤버는 protected 접근 지정자로 선언하여 다른 패키지에 있는 하위 클래스가 멤버에 접근이 가능하도록 해줍니다. 만일 private 접근 지정자로 선언해 주었다면 access 메서드(getter, setter)를 사용하여 접근할 수 있습니다.

//basicpk/Person.java
package basic;
public class Person {
	protected int age;
	private String name;
	
    //access 메서드
	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setAge(int age) {
		this.age = age;
	}
    
    //일반 메서드
	public void WhatYourName() {
		System.out.println(name);
	} 
	
	public void HowOldAreYou() {
		System.out.println(age+"세");
	}
}

자식 클래스인 UnivStudent는 부모 클래스의 멤버와 메서드를 모두 상속받았습니다. UnitStudent에서 멤버를 따로 선언하는 것이 가능합니다.
Person name이 default, public,protected 일 때는 직접 참조가 가능하여 name이라고만 작성해도 됩니다. 하지만 private일 때는 직접 참조가 불가능하여 this.getName()을 통해 접근이 가능합니다.

//basicpk/UnivStudent.java
package basic;
public class UnivStudent extends Person{
	public String major; 
	
	public void WhoAreYou() {
		System.out.println(this.getName());  
		System.out.println(age+"세"); //age가 protected이니 접근 가능
		System.out.println(this.major+"전공");
	}
}

위와 마찬가지로 main에서 객체를 선언주고 멤버에 접근할 때 age는 protected이니 s.age로 작성이 가능합니다. 하지만 name은 private이니 s.setName처럼 access 메서드를 통해 접근이 가능합니다.

//basicpk//StudentTest.java
import basic.UnivStudent;

public class StudentTest {

	public static void main(String[] args) {
		UnivStudent s=new UnivStudent();
		s.age(20);
		s.setName("홍길동");
		s.major="컴퓨터공학";
		s.WhoAreYou();
	}
}

📌 메서드 재정의

메서드 오버라이딩

  • sub클래스에서 super 클래스에서와 같은 이름의 멤버를 다시 정의합니다.
    • 기존의 멤버를 sub클래스에서 수정을 합니다.
  • super 클래스에서 상속된 멤버는 은폐됩니다.
    • 은폐된 멤버에 접근을 하고 싶을 때는 super 참조변수를 이용합니다.

this vs super

  • this
    • 부모 클래스로부터 상속받은 멤버는 자식 클래스에서 this 참조변수로 접근이 가능합니다.
      -> 부모로부터 상속받은 것이 자식 클래스의 멤버이기 때문입니다.
  • super
    • 메서드 오버라이딩으로 은폐된 상위 클래스의 메서드를 호출할 때 사용합니다.

java.lang.Object

특별히 상속관계를 명시하지 않았을 때 기본적으로 Object로부터 상속됩니다.

Person 클래스가 super 클래스이며 UnivStudent가 sub 클래스입니다.

@override

toString으로 재정의된 함수임을 나타내줍니다.

  • 재정의하면 좋을 Object 클래스의 메서드
    • String toString() : 현재 객체를 문자열로 표현합니다.
//overridingpk/Person.java
package overriding;

public class Person {
	protected int age;
	protected String name;
	

	public void WhatYourName() {
		System.out.println(name);
	} 
	
	public void HowOldAreYou() {
		System.out.println(age+"세");
	}
	
	public void WhoAreYou() {
		WhatYourName();
		HowOldAreYou();
	}

	@Override  //다음의 함수는 toString으로 재정의된 함수이다를 나타내줌
	public String toString() {
		return name+"("+age+"세)";
	}
}

자식 클래스에서 부모 클래스에서와 같은 이름의 메서드를 선언해 주는 것을 메서드 오버라이딩이라고 합니다. WhoAreYou()는 super 클래스에도 있지만 sub 클래스에서도 따로 정의를 하고 싶을 때 다음과 같이 작성이 가능합니다. 자식 클래스에서 WhoAreYou() 메서드를 재정의 해주니 부모한테 상속받은 WhoAreYou()는 은폐됩니다. 하지만 부모 클래스의 WhoAreYou()메서드를 사용을 하고 싶다면 super를 작성해주어 불러올 수 있습니다.

Object 클래스의 메서드인 String toString()도 super 참조변수를 이용하여 재정의가 가능합니다. 문자열에 넣고 싶은 내용도 추가할 수 있습니다.

//overridingpk/UnivStudent.java
package overriding;
public class UnivStudent extends Person{
	protected String major;
	
	public void WhoAreYou() {
		super.WhoAreYou();
		System.out.println(major+"전공");
	}

	@Override
	public String toString() {
		return super.toString()+" " +major+"전공 대학생";
	}
}

main에서는 문자열을 출력하듯이 생성한 참조변수를 출력해줄 수 있습니다.
System.out.prinln(s)처럼 작성이 가능합니다.

//overridingpk//StudentTest.java
package overriding;
public class StudentTest {

	public static void main(String[] args) {
		UnivStudent s=new UnivStudent();
		s.age=20;
		s.name="홍길동";
		s.major="컴퓨터공학";
		
		//s.WhoAreYou();
		System.out.println(s); //문자열처럼 출력하고 싶을 때 
		//s는 s.toString()과 같음
		System.out.println(s.toString()); 
	}

}

📌 하위 클래스의 생성자

상속과 생성자

  • 생성자를 이용하여 객체 생성과 동시에 각 멤버변수의 값을 초기화할 수 있습니다.
  • 하위 클래스 객체를 위한 생성자는 항상 하위 클래스에서 새롭게 정의를 해야 합니다.

하위 클래스의 생성자 구현

⭐ 상위 클래스의 생성자 호출을 통해 상속받은 멤버 변수들을 초기화 해야합니다.

하위 클래스의 생성자를 미구현시 자동으로 상위 클래스의 인자 없는 생성자가 호출됩니다.

super([인수리스트])

  • 상위 클래스 생성자를 호출할 때 사용합니다.
    • 반드시 하위 클래스 생성자의 첫 줄에 위치해야 합니다.
  • 하위 클래스의 생성자 안에 이 호출이 명시적으로 포함되어
    • 있으면
      • 상위 클래스의 인자 없는 생성자의 자동 호출은 생략됩니다.
    • 없으면
      • 상위 클래스의 인자 없는 생성자의 자동 호출이 일어납니다.

방법

  1. 인자 없는 생성자를 추가할 경우 아래 과정은 생략해줍니다. 자동으로 이루어지기 때문입니다.
  2. 상위 클래스에서 인자 있는 생성자를 추가해줍니다.
public Person(String name, int age) {
		this.age=age;
		this.name=name;
}
  1. 하위 클래스 생성자의 첫번째 줄에 상위 클래스 생성자를 호출합니다.
public UnivStudent(String name, int age, String major){
	super(name, age);
}
  1. 하위 클래스의 멤버는 this 참조변수를 이용하여 초기화해줍니다.
this.major=major;
  1. main에서 생성자를 초기화해줍니다.
UnivStudent s=new UnivStudent("홍길동",20,"컴퓨터공학");

전체 코드는 다음과 같습니다.

//superpk/Person.java
package superpk;

public class Person {
	protected int age;
	protected String name;
	
	public Person(String name, int age) {
		this.age=age;
		this.name=name;
	}
	
	public void WhatYourName() {
		System.out.println(name);
	} 
	
	public void HowOldAreYou() {
		System.out.println(age+"세");
	}
	
	public void WhoAreYou() {
		WhatYourName();
		HowOldAreYou();
	}

	@Override 
	public String toString() {
		return name+"("+age+"세)";
	}
}
//superpk/UnivStudent.java
package superpk;
public class UnivStudent extends Person{
	
	protected String major;
	public UnivStudent(String name, int age, String major) {
		super(name, age);
		this.major=major;
	}
	
	public void WhoAreYou() {
		super.WhoAreYou(); 
		System.out.println(major+"전공");
	} 
	
	@Override
	public String toString() {
		return super.toString()+" " +major+"전공 대학생";
	}
}
//superpk//StudentTest.java
package superpk;

public class StudentTest {

	public static void main(String[] args) {
		UnivStudent s=new UnivStudent("홍길동",20,"컴퓨터공학");
		
		s.WhoAreYou();
	}

}

💡 하위 클래스 작성시 유의점
1. private 멤버는 상속은 되나 직접 참조는 불가합니다. -> access 메서드를 이용합니다.
2. 하위 클래스의 생서자 첫 줄에서 상위 클래스의 생성자를 명시적으로 호출합니다.
3. 재정의 되어 은폐된 멤버는 super, 나머지 멤버는 this 참조변수로 접근합니다.

profile
여행하는 데이터 사이언티스트🧙‍♂️

0개의 댓글

관련 채용 정보