국비 14

냐아암·2023년 5월 3일
0

국비

목록 보기
18/114

상속

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

  • 장점
    코드 길이 감소
    코드 추가 빛 변경 용이
    코드 중복 제거 -> 프로그램 생산성, 유지보수성 증가

  • 표현식
    [접근제한자] class 클래스명 extends 부모 클래스명 {}


  • 오버라이딩
    자식 클래스가 상속받은 부모 메소드를 재정의 하는 것

  • 오버라이딩 성립 조건

  1. 메소드 이름 동일
  2. 반환형 동일
  3. 매개변수 동일
  4. 접근제한자가 같거나 더 넓은 범위여야 함
    ex) (부) protected -> (자) protected 또는 public
    *부모의 private 메소드는 오버라이딩 불가-> 자식이 접근할 수 없기 때문
  5. 예외처리 범위는 같거나 더 좁게 함

  • Object의 메소드인 toString() 사용
    *객체가 가지고 있는 모든 값(필드)를 하나의 문자열로 반환하는 용도의 메소드

    *print구문 수행 시 참조 변수명을 작성하면 자동으로 toString() 메소드를 호출해서 출력한다.

System.out.println(p.toString()); // 수지/30/한국
System.out.println(p); // 수지/30/한국

--> 동일한 결과값


  • super()
    부모 생성자 호출하는 코드 (반드시 자식 생성자 최상단에 작성)
    -> 자식 객체 내부에 부모 객체 생성
    -> 미작성 시 컴파일러가 자동 추가
    *부모 매개변수 생성자 호출

  • super.
    상속에서 자식 클래스 정의 시 부모 객체를 가르키는 참조변수
    자식 클래스 내에서 부모 클래스 객체에 접근하여 필드나 메소드 호출 시 사용

  • final
    더이상 상속 불가능

Person

package edu.kh.inheritance.model.vo;

public class Person extends Object{
	//class명에 상속 구문이 없다면
	//컴파일러가 자동으로 extends Object 구문을 추가
	
	// 필드
	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;
	}
	
	// 메소드
	//getter/setter
	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;
	}
	
	//상속의 특징: 코드 추가 및 수정이 용이
	//(새로운 메소드를 Person에 추가했을 때
	//Student와 Employee가 사용가능한지 확인)
	
	public void breath() {
		System.out.println("사람은 코나 입으로 숨을 쉰다.");
	}
	
	public void move() {
		System.out.println("사람은 움직일 수 있다.");
	}
	
	//상속받은 자식들에 대한 공통적인 규약 정의할 수 있다.
	//-> 상속받은 자식들은 모두 부모와 같은 필드, 메소드를 가지고 있으므로
	//	 클래스들이 일부 공통된 형태를 띈다.
	
	
	
	// Object.toString() 메소드 오버라이딩
	// - toString() 메소드는 객체가 가지고 있는 모든 값(필드)를
	//	 하나의 문자열로 반환하는 용도의 메소드
	
	@Override
	public String toString() {
		return name + "/" + age + "/" + nationality;
			//김철수 			15			대한민국
	}

}

Student

package edu.kh.inheritance.model.vo;

public class Student extends Person{
	//Student 클래스에 Person클래스 내용을 연장한다.
	// == Student 클래스에 Person 클래스 내용(필드, 메소드)을 추가하여 확장한다.
	
	//**상속**
	//extends: 확장하다 연장하다 + 
	
	// 필드
	
	private int grade; //학년
	private int classRoom; //반
	
	// 생성자
	public Student() {
		//Student() 객체 생성 시
		//내부에 상속받은 Person객체를 생성하기 위한
		//Person생성자 호출 코드가 필요하다.
		
		//super: 상위 <-> sub: 하위
		//super == Person
		
		super(); //super() 생성자
		//부모의 생성자를 호출하는 코드
		//반드시 자식 생성자 최상단에 작성되어야 함!!
		
		// *super() 생성자 때문에
		//	자식 객체 내부에 부모 객체가 생성된다.
		
		// *super() 생성자 미작성 시
		//	컴파일러가 컴파일 단게에서 자동으로 추가해줌
		
	}
	public Student(String name, int age, String nationality,
					int grade, int classRoom) {
		
		//전달받은 값 중 name, age, nationality
		//부모 필드에 세팅하기
		
		//this.name = name; //X
		//상속받은 부모의 필드(name)를
		//자식의 필드처럼 사용하려 했으나 오류 발생
		
		//왜? 부모의 필드에 private 접근 제한자가 있어서
		//자식이라도 다른 객체이기 때문에 직접 접근이 불가능
		//-> 간접 접근 방법 사용
		
		/*
		setName(name);
		setAge(age);
		setNationality(nationality);
		*/
		//부모의 setter 이용하면 되지만 비효율적
		
		super(name, age, nationality); //부모 매개변수 생성자 호출
		
		this.grade = grade;
		this.classRoom = classRoom;
	}
	
	
	// 메소드
	//getter/setter
	
	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;
	}
	
	//toString() 오버라이딩
	@Override
	public String toString() {
		return super.toString() //super 참조변수
				+ grade + "/" + classRoom;
	}

}

Employee

package edu.kh.inheritance.model.vo;

public class Employee extends Person {
					// Person 상속받음
	
	// 필드
	
	private String company;
	
	// 생성자
	public Employee() {} //단축키: ctrl space - constructor

	public Employee(String name, int age, String nationality, String company) {
		
		super(name, age, nationality); //3. 빼먹지 않기!!!!!!!!!!!
		this.company = company;
	} //단축키: ctrl alt s - generate using field

	
	// 메소드
	
	public String getCompany() {
		return company;
	}

	public void setCompany(String company) {
		this.company = company;
	}
	
	//Person으로부터 상속받은 메소드 중
	//move() 메소드를 Employee에 맞게 재정의(Overriding)
	
	//@Override 어노테이션: 해당 메소드가 오버라이딩되었음을
	//					 컴파일러에게 알려주는 역할
	
	//어노테이션(Annotation): 컴파일러에게 알려주기 위한 코드(컴파일러 인식용 주석)
	
	@Override //오버라이딩 시 작성해주는 것이 좋다. (생략할 수는 있음)
	public void move() {
		
		//기존 부모 코드 삭제 후 자식이 새롭게 재정의
		System.out.println("오버라이딩된 move()메소드");
		System.out.println("효율적으로 빨리 일처리하고 야근을 하지 않는다.");
		
	}
	
	//***오버라이딩 성립 조건***
	//1. 메소드 이름 동일
	//2. 반환형 동일
	//3. 매개변수 동일
	//4. 접근 제한자가 같거나 더 넓은 범위여야 함
	//	 ex) (부) protected -> (자) protected 또는 public
	//5. 예외처리 범위는 같거나 더 좁게 함
	
	//  +부모의 private 메소드는 오버라이딩 불가
	//-> 자식이 접근할 수 없기 때문
	
	
	//toString() 오버라이딩
	@Override
	public String toString() {
		return super.toString() + "/" +company;
	} ;//2. super. 쓰려면 매개변수에서 super() 썼는지 확인!!!!!!!!!!
	
	
}

InheritanceService

package edu.kh.inheritance.model.service;

import java.util.Scanner;

import edu.kh.inheritance.model.vo.Employee;
import edu.kh.inheritance.model.vo.Person;
import edu.kh.inheritance.model.vo.Student;

public class InheritanceService {

	public void ex1() {
		// 상속 확인
		// - Person을 상속 받은 Student가 
		//	 Person의 필드, 메소드를 사용할 수 있는가
		
		Person p = new Person();
		
		//p.name = "홍길동"; -> private 때문에 직접 접근 불가
		
//		p = new Person("홍길동", 25, "대한민국");
		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 객체 생성
		Student std = new Student();
		
		//Student만의 고유한 메소드
		std.setGrade(3);
		std.setClassRoom(5);
		
		//Person 클래스로부터 상속받은 메소드
		std.setName("고아라");
		std.setAge(19);
		std.setNationality("대한민국");
		
		System.out.println(std.getGrade());
		System.out.println(std.getClassRoom());
		
		//Student가 Person의 메소드뿐만 아니라 필드도 상속받았는지 확인-잘 출력됨
		System.out.println(std.getName());
		System.out.println(std.getAge());
		System.out.println(std.getNationality()); 
		
		System.out.println("==============================");
		
		Employee emp = new Employee();
		
		//Employee만의 고유 메소드
		emp.setCompany("KH정보교육원");
		
		//Person 클래스로부터 상속받은 메소드
		emp.setName("다나카");
		emp.setAge(35);
		emp.setNationality("일본");
		
		System.out.println(emp.getCompany());
		
		System.out.println(emp.getName());
		System.out.println(emp.getAge());
		System.out.println(emp.getNationality());
		
		System.out.println("============================");
		
		//추가된 breath 메소드 확인하기
		p.breath();
		std.breath();
		emp.breath();
	}
	public void ex2() {
		
		//super() 생성자 사용 방법
		
		//Student 매개변수 5개짜리 생성자
		Student std = new Student("김캥거루", 20, "호주", 3, 5);
		
		System.out.println(std.getName());
		System.out.println(std.getAge());
		System.out.println(std.getNationality());
		System.out.println(std.getGrade());
		System.out.println(std.getClassRoom());
		

	}
	public void ex3() {
		//오버라이딩 확인 예제
		
		Student std = new Student();
		Employee emp = new Employee();
		
		std.move(); //오버라이딩 X -> Person의 메소드 수행
		//사람은 움직일 수 있다.
		
		emp.move(); //오버라이딩 O -> Employee 메소드 수행
		//오버라이딩된 move()메소드
		//효율적으로 빨리 일처리하고 야근을 하지 않는다.
	}
	
	public void ex4() {
		
		//모든 클래스는 Object클래스의 후손
		// == 모든 클래스의 최상위 부모는 Object
		
		//1) Object 상속 여부 확인
		Person p = new Person(); //Object를 상속받은 Person 객체 생성
		
		Student std = new Student(); //Person을 상속받은 Student 객체 생성
		//Object - Person - Student
		
		Scanner sc = new Scanner(System.in);
		
		String str = "abc";
		
		
		// ** Object 상속과 단계적인 상속 확인
		
		System.out.println(p.hashCode()); //Object에서 물려받은 hashCode()
		
		System.out.println(std.getAge()); //Person에서 물려받은 getAge()
		
		System.out.println(std.hashCode()); 
		//Person이 Object에서 물려받은 hashCode를 Student가 또 물려받아 사용
		
		//-> 무한 상속 가능
		
		//* Object가 모든 클래스의 최상위 부모인지 확인
		System.out.println(sc.hashCode());
		//Object - hashCode() 
		
		System.out.println(str.hashCode());
		//String - hashCode()
		// -> String이 Object에게 물려받은 hashCode()를 오버라이딩함
	
		
	}
	public void ex5() {
		
		Person p = new Person("수지", 30, "한국");
		
		System.out.println(p.toString()); // 수지/30/한국
		System.out.println(p); // 수지/30/한국
		
		//print구문 수행 시 참조 변수명을 작성하면
		//자동으로 toString() 메소드를 호출해서 출력한다.
		
		System.out.println("=============================");
		
		Student std = new Student("윈터", 27, "미국", 2, 6);
		
		System.out.println(std.toString()); //윈터/27/미국
		//1) Student 클래스 toString() 오버라이딩 전
		//Person으로부터 상속받은 오버라이딩된 toString() 수행
		
		//2) Student 클래스 toString() 오버라이딩 후
		//Student의 toString() 수행
		Employee emp = new Employee("김근로", 26, "한국", "00증권");
		System.out.println(emp.toString()); //1. 클래스에 오버라이드 했는지 확인!!!!
	}
}

매개변수 생성자와 오버라이딩에 각각 super을 작성했는지 확인

InheritanceRun

package edu.kh.inheritance.run;

import edu.kh.inheritance.model.service.InheritanceService;

public class InheritanceRun {

	public static void main(String[] args) {

		InheritanceService service= new InheritanceService();
		
//		service.ex1();
//		service.ex2();
//		service.ex3();
//		service.ex4();
		service.ex5();
		
		
	}

}

Parent

package edu.kh.inheritance.model.vo;

public /*final*/ class Parent { //부모 클래스
	//Object 상속 중
	
	//**final 클래스**
	// -> 마지막 클래스라는 의미로 "더이상 상속 불가능"
	
	public /*final*/ void method() {
		
		System.out.println("테스트용 메소드");
		
	}

}

Child


package edu.kh.inheritance.model.vo;

public class Child extends Parent{ //자식 클래스
					//Parent 상속 중
	
	//The type Child cannot subclass the final class Parent
	//(final 클래스인 Parent는 Child 클래스를 자식으로 가질 수 없다.)
	
	
	@Override
	public void method() {
		//Cannot override the final method from Parent
		System.out.println("오버라이딩 성공");
	}
	
	
	

}
profile
개발 일지

0개의 댓글