일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- Matrix
- SQL
- Binary Search
- java
- dynamic programming
- Binary Tree
- greedy
- Class
- array
- implement
- Stack
- 코테
- 코딩테스트
- Number Theory
- sorting
- Method
- Counting
- 자바
- two pointers
- Math
- database
- Data Structure
- hash table
- bit manipulation
- string
- 구현
- 파이썬
- geometry
- Tree
- simulation
- Today
- Total
코린이의 소소한 공부노트
추상 클래스, 추상 메서드 본문
앞서 클래스를 객체를 만드는 설계도로 표현했었다. 이번에 공부할 추상 클래스는 미완성 설계도로 표현할 수 있다.
[추상 클래스]
1. 미완성 메서드를 갖고 있는 클래스다.
abstract class Person{ // 제어자를 붙여 추상 클래스임을 알려준다.
abstract void eat(String s); // 추상 메서드
abstract void introduce(); // 추상 메서드
}
Person 안에 선언된 메서드들은 제어자 abstract가 있고 구현부가 없다. 이렇게 구현부가 없는 메서드를 추상 메서드라고 한다. 그리고 이런 추상 메서드를 갖고 있는 클래스를 추상 클래스라고 한다.
2. 다른 클래스 작성에 도움을 주기 위한 클래스로, 인스턴스를 생성할 수 없다.
Person p = new Person(); // error
미완성 설계도로 제품을 다 만들 수 없듯, 미완성 클래스인 추상 클래스로 객체를 생성할 수 없다.
3. 상속을 통해 추상 메서드를 완성해야 인스턴스를 생성할 수 있다.
class Student extends Person{ // 추상 클래스 상속받은 후
void eat(String s) { /* 먹기 */ } // 추상 메서드를
void introduce() { /* 학생입니다. */ } // 구현해주면
}
// 메인 내부
Student s = new Student(); // 인스턴스를 만들 수 있다.
Person p = new Student(); // 조상-자손 타입이라 가능한 선언
p.eat(); // Student의 eat이 호출된다.
[추상 메서드]
1. 선언부만 있고 구현부가 없는 미완성 메서드이다.
abstract 리턴타입 메서드이름(매개변수);
추상 클래스 내부에 위와 같이 만들어주면 된다. 구현부가 없으므로 주석으로 어떤 일을 하는 메서드를 만들 건지 적어놓는 것이 협업할 때 도움이 된다.
2. 꼭 필요한 기능이지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용한다.
abstract class Teacher extends Person{ // abstract가 붙음
void introduce() { /* 선생입니다. */ } // 1개의 메서드만 구현함
}
// 추상 클래스를 상속받았을 때
// 추상 클래스 내부의 모든 추상 메서드를 구현하지 않는다면
// 자손 클래스 또한 추상 클래스가 된다.
Person을 상속받은 Student과 Teacher 클래스에서 각각 introduce 메서드를 구현하려 한다. 직업이 무엇이냐에 따라 자기소개가 달라지기 때문에 introduce 메서드는 자손 클래스마다 기능이 다를 것이다. 이럴 때 introduce 메서드를 추상 메서드로 선언해놓고 자손에서 구현부를 작성하게끔 만들어줘야 한다.
3. 코드 작성 시 추상 메서드 호출 코드를 쓸 수 있다.
위에서 작성한 코드를 실행 가능하게 바꿔보면 다음과 같다.
// 메인 내부에서 실험
Person p = new Student(); // 다형성
p.eat("치킨"); // "치킨 냠냠!"
// 클래스 코드
abstract class Person{
String name;
int age;
String food;
Person() { } // 추상 클래스도 생성자가 있어야 한다.
abstract void eat(String s);
abstract void introduce();
void eat() {
eat(food); // 1) 추상 메서드를 호출해도 컴파일 에러는 나지 않는다.
}
}
class Student extends Person{
void eat(String s) { // 2) 자손 클래스에서 구현해야 호출시 사용 가능하다.
this.food = s;
System.out.println(food + " 냠냠!");
} // 3) 이 부분이 구현되어있지 않다면 컴파일 에러가 발생한다.
void introduce() {
System.out.println("학생 " + name + "입니다.");
}
}
abstract class Teacher extends Person{
void introduce() {
System.out.println("선생 " + name + "입니다.");
}
}
1) Person 클래스 내부에 인스턴스 메서드 eat()이 추상 메서드를 호출했다. 메서드 호출은 선언부만 알면 할 수 있는 것이기 때문에 에러가 발생하지 않는다.
2) 다만, 호출 시 사용 가능하게 하려면 Person을 상속받은 자손 클래스에서 eat 메서드가 구현되어야 한다.
- Person 클래스는 추상 클래스이므로 객체 생성이 불가능하다.
- Person 클래스 내부에 있는 eat()은 객체가 생성되어야 사용 가능한 im이다.
- 객체가 생성이 되려면 자손 클래스에서 추상 메서드를 완성을 시켜줘야 한다.
- 따라서 Person 클래스 내부에 있는 eat()을 사용하려면 구현 클래스(추상 메서드가 없는 클래스) Student에서 eat(String s) 메서드를 구현해야 한다.
3) 만약 구현되어있지 않다면 컴파일 에러가 발생한다.
- Student 클래스는 추상 클래스가 아니므로, 상속받은 모든 추상 메서드를 구현해야 한다. 따라서 eat 메서드가 구현되어있지 않다면 에러가 발생한다.
- 만약 Student 클래스에서 eat 메서드를 구현하지 않는다면, Student 클래스도 추상 클래스로 만들어야 컴파일 에러가 발생하지 않는다. 다만 메인에서 Person p = new Student(); 코드를 사용하지 못할 뿐이다. 추상 클래스로는 객체를 생성할 수 없기 때문이다.
- Teacher 클래스는 추상 클래스이므로, 상속받은 모든 추상 메서드를 다 구현할 필요는 없다. 위 코드에는 없지만, Teacher 클래스 내부에는 abstract void eat(String s); 코드가 숨어있다.
'Java' 카테고리의 다른 글
인터페이스 선언, 상속, 구현 (0) | 2022.05.13 |
---|---|
추상 클래스 작성하기 (0) | 2022.05.11 |
다형성의 장점 (0) | 2022.05.04 |
instanceof 연산자 (0) | 2022.05.03 |
참조변수의 형변환 (0) | 2022.04.20 |