상속
다른 클래스가 가지고 있는 멤버(필드, 메소드)들을 새로 작성할 클래스에서 직접 만들지 않고 상속받음으로써 새 클래스가 자신의 멤버처럼 사용할 수 있는 기능
장점
코드 길이 감소
코드 추가 빛 변경 용이
코드 중복 제거 -> 프로그램 생산성, 유지보수성 증가
표현식
[접근제한자] class 클래스명 extends 부모 클래스명 {}
오버라이딩
자식 클래스가 상속받은 부모 메소드를 재정의 하는 것
오버라이딩 성립 조건
Object의 메소드인 toString() 사용
*객체가 가지고 있는 모든 값(필드)를 하나의 문자열로 반환하는 용도의 메소드
*print구문 수행 시 참조 변수명을 작성하면 자동으로 toString() 메소드를 호출해서 출력한다.
System.out.println(p.toString()); // 수지/30/한국
System.out.println(p); // 수지/30/한국
--> 동일한 결과값
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 대한민국
}
}
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;
}
}
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() 썼는지 확인!!!!!!!!!!
}
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을 작성했는지 확인
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();
}
}
package edu.kh.inheritance.model.vo;
public /*final*/ class Parent { //부모 클래스
//Object 상속 중
//**final 클래스**
// -> 마지막 클래스라는 의미로 "더이상 상속 불가능"
public /*final*/ void method() {
System.out.println("테스트용 메소드");
}
}
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("오버라이딩 성공");
}
}