본문 바로가기

Java/공부

[Java] 상속 (Inheritance)

상속 (Inheritance)

1) 정의

- 다른 클래스가 가지고 있는 멤버 (필드, 메소드)들을 새로 작성할 클래스에서 직접 만들지 않고 상속을 받음으로써 새 클래스가 자신의 멤버처럼 사용할 수 있는 기능

- 자바에서는 단일상속만 지원함

 

2) 목적

- 클래스의 재사용

- 연관된 일련의 클래스들에 대한 공통적인 규약 정의

 

3) 장점

- 보다 적은 양의 코드로 새로운 클래스 작성 가능

- 코드를 공통적으로 관리함 - 코드의 추가 및 변경 용이

- 코드의 중복 제거 - 생산성, 유지보수 향상

 

4) 작성법

[접근제한자] class 클래스명 extends 클래스명 { }

 

5) 특징

- 모든 클래스는 Object 클래스의 후손

- 부모 클래스의 생성자, 초기화 블록은 상속되지 않음

- 부모의 private멤버는 상속은 가능하지만 직접 접근이 불가능

 

ex) 같은 프로젝트 내 2개의 클래스를 생성 ( Person , Student )

public class Person { 

	// 필드
	private String name;
	private int age;
	private String nationality;
    
	// 생성자
   	public Person() {

	}
    
	public Person(String name, int age, String nationality) {
		this.name = name;
		this.age = age;
		this.nationality = nationality;
	}
    
	// 메서드
	public String getName() {
		return name;
	}

	public void setName(String name) {

		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public String getNationality() {
		return nationality;
	}
	
	public void setNationality(String nationality) {
		this.nationality = nationality;
	}    
}

---------------------------------------------------------
public class Student extends Person { 

	// 필드
	private int grade;
	private int classRoom;
    
	// 생성자
	public Student() { }
    
  	// 메서드
   	public int getGrade() {
		return grade;
	}

	public void setGrade(int grade) {
		this.grade = grade;
	}

	public int getClassRoom() {
		return classRoom;
	}

	public void setClassRoom(int classRoom) {
		this.classRoom = classRoom;
	}

 

  1. Person을 상속받은 Strudent가 Person의 필드, 메소드를 사용할 수 있을까? (O)

		Person p = new Person();
		
		p.setName("홍길동");
		p.setAge(25);
		p.setNationality("한국");
		
		System.out.println(p.getName());
		System.out.println(p.getAge());
		System.out.println(p.getNationality());
		
		System.out.println("--------------------------");
		
		Student std = new Student();
		
        std.setName("무무");
		std.setAge(7);
		std.setNationality("한국");
		std.setGrade(3);
		std.setClassRoom(5);
        
        System.out.println(std.getName());        // Person의 필드
		System.out.println(std.getAge());         // Person의 필드
		System.out.println(std.getNationality()); // Person의 필드
		System.out.println(std.getClassRoom());
		System.out.println(std.getGrade());
        
        // Student가 People의 필드, 메소드 정상 사용가능
        // 단, std.name = "홍길동"; -> 이런식의 직접 접근은 불가

 

  2. super() 생성자 사용방법

	// class Student의 생성자 부분만 발췌함
	public Student() {
		super();
	// 부모의 생성자를 호출하는 코드, 반드시 자식 생성자 최상단에 작성돼야 함	
	// super() 생성자 때문에 자식 객체 내부에 부모 객체가 생성됨
	// super() 생성자 미작성시 컴파일러가 컴파일단계에서 자동으로 추가해줌
		
	}
    
	public Student(String name, int age, String nationality, int grade, int classRoom) {

	// this.name = name; 처럼 부모의 필드를 자식의 필드처럼 사용시
	// private접근 제한자로 인헤 에러 발생 (직접 접근 불가, 간접 접근 필요)
		
	super(name, age, nationality); // 간접적으로 부모 매개변수 생성자 호출
	this.grade = grade;
	this.classRoom = classRoom;
		
	}

 

오버라이딩 (Overriding)

1) 정의

- 자식클래스가 상속받은 부모 메소드를 재작성 하는 것

- 자식 객체를 통한 오버라이딩시 후손의 메소드가 부모의 메소드보다 우선권을 가짐

 

2) 특징

- 메소드 헤드라인 위에 반드시 @Override Annotation을 표기해줘야함

- 접근 제어자를 부모의 것과 같거나 넓은 범위로 변경 가능

- 부모 메소드의 예외처리 클래스 처리범위보다 좁은 범위로 예외처리 클래스 수정 가능

 

3) 성립조건

- 메소드 이름이 동일해야함

- 매개변수의 개수, 타입, 순서가 동일해야함

- 리턴타입이 동일해야함

- private메소드는 오버라이딩 불가함

 

ex) Object 클래스의 toString()메소드를 순차적으로 오버라이딩하기

  * toString( ) :

    객체를 문자열로 나열할 수 있는 가장 효율적인 메서드!

    print구문 수행시 참조 변수명을 작성하면 자동으로

    Object의 toString을 호출해 객체에 포함된 문자열을 출력해준다. 

	// Person, Student의 메소드 부분만 발췌함
    
        // 1) Object의 toString() -> Person 에서 오버라이딩
    
	@Override // 어노테이션 필수!
	public String toString() {
		return name + " / " + age + " / " + nationality;
	}
    
	Person p = new Person("김개똥", 20, "한국");
	System.out.println(p.toString());
	// 오버라이딩된 Person의 toString()이 실행된다
    
	--------------------------------------------------------
	// 2) Person의 toString() -> Student 에서 오버라이딩
    
	@Override // 어노테이션 필수!
	public String toString() {
		return super.toString() + " / " + grade + " / "+classRoom;
		// 이 때, Person 필드의 private name, age, nationality 직접 호출시 오류 발생
		// super.toString()을 이용해 간접적으로 호출하기
	}
    
	Student std = new Student("이백점",18, "미국", 2, 6);
	System.out.println(std.toString());
	// 오버라이딩된 Student의 toString()이 실행된다

 

final 클래스

1) 정의

- 상속이 불가능한 클래스

 

2) 작성법

public final class [클래스명] { }

 

 

▶ final 메소드

1) 정의

- 상속시 오버라이딩이 불가능한 메소드

 

2) 작성법

public final void [메소드명]() { }

 

ex) final 클래스와 final 메소드 생성시, 후손 class 생성 불가 + 부모 메서드 오버라이딩 불가

public final class Parent { 

	public final void method () {
		System.out.println("테스트용 메서드");
	}	
    
}

---------------------------------------------------
public class Child extends Parent{
	// final class Parent는 상속 불가 (오류발생)

	@Override
	public void method() {
		// final method는 오버라이딩 불가 (오류발생)
		System.out.println("오버라이딩");
	}
}