추상클래스
- 추상클래스는 미완성 설계도에 비유할 수 있다. 클래스가 미완성이라는 것은 멤버의 개수에 관계된 것이 아니라, 단지 미완성 메서드(추상메서드)를 포함하고 있다는 의미이다.
- 미완성 설계도로 완성된 제품을 만들 수 없듯이 추상클래스로 인스턴스는 생성할 수 없다. 추상클래스는 상속을 통해서 자손클래스에 의해서만 완성될 수 있다.
- 추상클래스는 새로운 클래스를 작성하는데 있어서 바탕이 되는 조상클래스로서 중요한 의미를 갖는다. 즉 서로 다른 세 개의 클래스를 따로 그리는 것보다는 이들의 공통부분만을 그린 추상클래스를 만들어 놓고, 이 추상클래스를 이용해서 각각의 설계도를 완성하는 것이 훨씬 효율적이다.
└ex. 사람이라는 클래스가 있으며 걷다라는 메서드가 존재한다. 또한 사람클래스를 상속받는 영희와 철수 클래스가 존재한다. 사람의 걷다라는 공통 메서드를 상속받은 영희와 철수가 사용할 수 있다. 그러나 사람마다 걷는 속도가 다르기 때문에 사람마다 그 속도를 조절해 주어야한다. 이때 만약 사람 클래스에서 걷다라는 메서드를 일반 메서드로 지정하면 사람클래스를 상속받는 영희와 철수 클래스는 모두 같은 속도로 걸을 수 밖에 없게 된다. 하지만 걷다라는 메서드를 추상메서드로 정의하고 영희와 철수 클래스에서 각각 구현해주면 영희와 철수는 자신의 걸음걸이대로 걸을 수 있게된다.
-----------------------------------------------------------
예제1.
class Person{
public void walk(){
System.out.println("천천히 걷습니다.");
}
}
class Younghee extends Person{}
class Chulsu extends Person{}
public class Test {
public static void main(String[] args) {
Younghee y = new Younghee();
Chulsu c = new Chulsu();
y.walk();
c.walk();
}
}
실행결과
천천히 걷습니다.
천천히 걷습니다.
-----------------------------------------------------------
예제2.
abstract class Person{
abstract void walk();
}
class Younghee extends Person{
void walk(){
System.out.println("천천히 걷습니다.");
}
}
class Chulsu extends Person{
void walk(){
System.out.println("빨리 걷습니다.");
}
}
public class Test {
public static void main(String[] args) {
Younghee y = new Younghee();
Chulsu c = new Chulsu();
y.walk();
c.walk();
}
}
실행결과
천천히 걷습니다.
빨리 걷습니다.
-----------------------------------------------------------
- 여기서 '그냥 오버라이딩해서 사용하면 안되나요?'하고 생각할 수 도 있는데, 굳이 abstract를 붙여서 추상메서드로 선언하는 이유는 자손 클래스에서 추상메서드를 반드시 구현하도록 강요하기 위해서이다. 만일 추상메서드로 정의되어 있지 않고 빈 몸통만 가진 일반메서드로 정의되어 있다면, 상속받는 자손 클래스에서는 이 메서드들이 온전히 구현된 것으로 인식하고 오버라이팅을 통해 자신의 클래스에 맞도록 구현하지 않을 수도 있기 때문이다.
- 문법
abstract class 클래스명 { ... }
- 좀 더 쉽게 이해하고 싶다면 추상클래스를 미완성클래스라고 인식하기보다 그저 구현부가 없는 추상메소드를 포함하고 있는 클래스라고 생각하라.
- 일반클래스와 전혀 다르지 않다. 추상클래스에도 생성자가 있으며, 멤버변수와 메서드도 가질 수 있다.
[참고] 추상메서드를 포함하고 있지 않은 클래스에도 키워드 'abstract'를 붙여서 추상클래스로 지정할 수도 있다. 추상메서드가 없는 완성된 클래스라 할지라도 추상클래스로 지정되면 클래스의 인스턴스를 생성할 수 없다.
추상메서드(abstract mmethod)
- 일반 메서드는 선언부와 구현부로 구성되어 있는 반면에 추상메서드는 선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 것이 추상메서드이다. 즉, 설계만 해 놓고 실제 수행될 내용은 작성하지 않았기 때문에 미완성 메서드인 것이다.
└why? 상속받는 클래스에 따라 달라질 수 있기 때문에 조상 클래스(추상클래스)에서는 선언부만을 작성하고, 실제 내용은 상속받는 클래스에서 구현하도록 비워 두는 것이다.
- 문법
/*주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다.*/
abstract 리턴타입 메서드명(); // 구현부가 없으므로 괄호{}대신 문장의 끝을 알리는 ';'을 적는다.
- 추상클래스로부터 상속받는 자손클래스는 오버라이딩을 통해 조상인 추상클래스의 추상메서드를 모두 구현해주어야 한다. 만일 조상으로부터 상속받은 추상메서드 중 하나라도 구현하지 않는다면, 자손클래스 역시 추상클래스로 지정해 주어야 한다.
- 메서드를 사용하는 쪽에서는 메서드가 실제로 어떻게 구현되어있는지 몰라도 메서드의 이름과 매개변수, 리턴타입, 즉 선언부만 알고 있으면 되므로 내용이 없을 지라도 추상메서드를 사용하는 코드를 작성하는 것이 가능하며, 실제로는 자손클래스에 구현된 완성된 메서드가 호출되도록 할 수 있다.
추상클래스의 작성
- 상속이 자손 클래스를 만드는데 조상 클래스를 사용하는 것이라면, 이와 반대로 추상화는 기존의 클래스의 공통부분을 뽑아내서 조상 클래스를 만드는 것이라고 할 수 있다.
- 상속계층도를 따라 내려갈수록 클래스는 점점 기능이 추가되어 구체화 정도가 심해지며, 상속계층도를 따라 올라갈수록 클래스는 추상화의 정도가 심해진다고 할 수 있다. 즉, 상속계층도를 따라 내려 갈수록 세분화되며, 올라갈수록 공통요소만 남게 된다.
추상화 - 클래스간의 공통점을 찾아내서 공통의 조상을 만드는 작업
구체화 - 상속을 통해 클래스를 구현, 확장하는 작업
- 또한 추상클래스를 상속받는 클래스들의 인스턴스들을 하나의 묶음으로 다룰 수 있다. 다형성에서 배웠듯이 조상 클래스타입의 참조변수로 자손 클래스의 인스턴스를 참조하는 것이 가능하기 때문에 조상클래스타입에 자손 클래스의 인스턴스를 담을 수 있는 것이다.
- 조상클래스에 추상메서드가 정의되어 있다 하더라도 메서드는 참조변수의 타입에 관계없이 실제 인스턴스에 구현된 것이 호출된다.
[참고] 추상클래스를 떠나서도 메서드는 참조변수의 타입에 관계없이 실제 인스턴스에 구현된 것이 호출된다. 예제 참고.
-----------------------------------------------------------
예제1.
class Person{
void walk(){
System.out.println("걷습니다.");
}
}
class Younghee extends Person{
void walk(){ //Overiding
System.out.println("천천히 걷습니다.");
}
}
public class Test {
public static void main(String[] args) {
Person y = new Younghee(); // 다형성 및 promtion을 볼 수 있다.
y.walk();
}
}
실행결과
천천히 걷습니다.
-----------------------------------------------------------
- Younghee()객체를 만들어 Person 타입의 참조변수 y에 대입하였으므로 walk()메서드를 호출할경우 Person의 walk()가 호출될것 같으나 메서드는 참조변수의 타입에 관계없이 실제 인스턴스에 구현된 것이 호출되기 때문에 Younghee의 walk()가 호출된다.
-----------------------------------------------------------
class Person{
String name = "사람";
}
class Younghee extends Person{
String name = "영희";
}
public class Test {
public static void main(String[] args) {
Person y = new Younghee();
System.out.println(y.name);
}
}
실행결과
사람
-----------------------------------------------------------
- 다형성을 이용해 자손클래스의 인스턴스를 조상클래스 타입으로 참조하게 했을 경우, 조상클래스의 메서드와 조상클래스와 자손클래스의 교집합된 메서드만 visible된다.
-------------------------------------------------------------------
class Person{
String name = "사람";
void walk(){}
void sleep(){}
}
class Younghee extends Person{
String name = "영희";
void draw(){}
}
public class Test {
public static void main(String[] args) {
Person y = new Younghee();
y.walk();
y.sleep();
y.draw(); // error msg : The method draw() is undefined for the type Person
Younghee yh =(Younghee)y; // casting
yh.draw();
}
}
-------------------------------------------------------------------
'예전 포스팅 모음' 카테고리의 다른 글
[DB] Transaction, Select, update, delete, truncate (0) | 2014.09.19 |
---|---|
[java] 인터페이스(interface) (0) | 2014.09.18 |
[DB] 오라클 구조, sqlplus.exe 사용법, 테이블 생성, 레코드 추가 (0) | 2014.09.18 |
[DB] RDBMS(Relationship Database management System, 관계형 데이터베이스)란? (0) | 2014.09.18 |
[java] 쓰레드(Thread) (0) | 2014.09.15 |