기존의 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법 요소
상속을 사용하는 이유?
코드를 재사용하여 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있어 코드의 중복을 제거할 수 있고, 다형적 표현이 가능하다는 장점이 있다.
class Student {
String name;
int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
void learn(){
System.out.println("교양수업을 듣습니다.");
};
}
class CsStudent extends Student { // Student 클래스로부터 상속. extends 키워드 사용
String companyName;
void coding(){
System.out.println("코딩수업을 듣습니다.");
};
}
class MathStudent extends Student { // Student 클래스로부터 상속
String mathformula;
void formula(){
System.out.println("근의 공식을 사용합니다.");
};
}
public class HelloJava {
public static void main(String[] args){
//Person 객체 생성
Student s = new Studnet();
s.name = "학생";
s.age = 24;
p.learn();
System.out.println(s.name);
//Programmer 객체 생성
CsStudent cs = new CsStudent();
cs.name = "박해커";
cs.age = 26;
cs.learn(); // Persons 클래스에서 상속받아 사용 가능
pg.coding(); // Programmer의 개별 기능
System.out.println(pg.name);
}
}
//출력값
교양수업을 듣습니다.
학생
교양수업을 듣습니다.
코딩수업을 듣습니다.
박해커
자바의 객체지향 프로그래밍에서는 단일 상속만을 허용한다.
다만 인터페이스라는 문법 요소를 통해 다중 상속과 비슷한 효과를 낼 수 있는 방법이 있다.
상속처럼 클래스를 재사용할 수 있는 방법으로, 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것을 의미
public class Computer {
String os;
Keyboard keyboard;
public Computer(String os, Keyboard keyboard) {
this.os = os;
this.keyboard = keyboard;
}
void showInfo() {
System.out.println("os : " + os);
System.out.println(keyboard.company+ " " + keyboard.name);
}
public static void main(String[] args) {
Keyboard keyboard1 = new Keyboard("로지텍", "무선 키보드");
Keyboard keyboard2 = new Keyboard("로지텍", "유선 키보드");
Computer c = new Computer("window", keyboard1);
Computer c2 = new Computer("mac os", keyboard2);
c.showInfo();
c2.showInfo();
}
}
class Keyboard {
String company, name;
public Address(String company, String name) {
this.company = company;
this.name = name;
}
}
// 출력값
os : window
로지텍 무선 키보드
os : mac os
로지텍 유선 키보드
컴퓨터 클래스 안에 키보드 클래스를 참조변수로 사용한다.
그럼 상속관계, 포함관계 어떤 기준으로 판별해야 하나?
가장 쉬운 방법은 클래스 간의 관계가 ~은 ~이다(IS-A) 혹은 ~은 ~을 가지고 있다(HAS-A) 관계인지 생각해보면 쉽다.
상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의 하는 것
public class Main {
public static void main(String[] args) {
Math math = new Math();
Korean korean = new Korean();
English english = new English();
math.learn();
korean.learn();
english.learn();
}
}
class Study {
void learn() {
System.out.println("공부를 합니다.");
}
}
class Math extends Study {
void learn() {
System.out.println("수학 공부를 합니다.");
}
}
class Korean extends Study {
void learn() {
System.out.println("국어 공부를 합니다.");
}
}
class English extends Study {
void learn() {
System.out.println("영어 공부를 합니다.");
}
}
// 출력값
수학 공부를 합니다.
국어 공부를 합니다.
영어 공부를 합니다.
위 예시처럼 Study 클래스를 상속 받은 하위 클래스들은 상위 메서드인 learn 메서드를 자신의 클래스에 맞게 재정의 하였다.
메서드 오버라이딩 세 가지 조건
super는 상위 클래스의 객체, super()는 상위 클래스의 생성자를 호출하는 것
공통적으로 모두 상위 클래스의 존재를 상정하며 상속 관계를 전제
public class Example {
public static void main(String[] args) {
SubClass subClass = new SubClass();
subClass.callNum();
}
}
class SuperClass {
int count = 20; // super.count
SuperClass(){
System.out.println("상위 클래스 생성자");
}
}
class SubClass extends SuperClass {
int count = 15; // this.count
SubClass(){
super();
System.out.println("하위 클래스 생성자");
}
void callNum() {
System.out.println("count = " + count);
System.out.println("this.count = " + this.count);
System.out.println("super.count = " + super.count);
}
}
// 출력값
상위 클래스 생성자
하위 클래스 생성자
count = 15
count = 15
count = 20
하위 클래스는 상위 클래스의 count를 상속 받는데 인스턴스 변수가 같아 구분할 방법이 필요하다.
두 개의 같은 이름의 변수를 구분하기 위한 방법으로 super키워드를 사용
super() 메서드를 사용하여 상위 클래스 생성자를 호출한다.
만약 super()가 없는 경우에는 컴파일러가 생성자의 첫 줄에 자동으로
super()를 삽입한다.
이때 상위 클래스에 기본 생성자가 없으면 에러가 발생한다.
따라서 클래스를 만들 때 자동으로 기본 생성자를 생성하는 것을 습관화하는 것이 좋다.
클래스 상속 계층도에서 최상위에 위치한 상위 클래스이다.
아무런 상속을 받지 않는 클래스는 자동적으로 extends Object를 추가하여 상속받도록 한다.
특정 객체 안에 관련된 속성과 기능을 하나의 캡슐로 만들어 데이터를 외부로부터 보호하는 것
가장 큰 장점은 정보 은닉
클래스들을 그룹 단위로 묶어 효과적으로 관리하기 위한 목적을 가지고 있다.
패키지로 클래스를 묶는 것의 장점은 클래스의 충돌을 방지해주는 기능
Import문은
다른 패키지 내의 클래스를 사용하기 위해 사용
클래스, 필드, 메서드, 생성자 등에 부가적인 의미를 부여하는 키워드
접근 제어자
기타 제어자
하나의 대상에 대해서 여러 제어자를 사용할 수 있지만, 접근 제어자는 각 대상에 대해 단 한번만 사용할 수 있다.
접근 제한 범위
public -> protected -> default -> private
setter 메서드를 통해 데이터를 넣고 getter 메서드를 통해 데이터를 읽어온다.