코드일기장

[Java/OOP] 추상클래스 (abstract class) 본문

Java/OOP

[Java/OOP] 추상클래스 (abstract class)

won_hyeok2 2022. 4. 29. 21:17

 

추상클래스

 

 

  추상클래스는 미완성 클래스라고 보면 된다. 말 그대로 완성되지 않은 클래스이다. 

 

abstract class Game{  //추상클래스(미완성 클래스)
	abstract void play(int pos); //추상 메서드 (몸통 {}이 없는 미완성메서드)
	abstract int score();
}
public class ArrayListEx1 {
	public static void main(String[] args)throws IOException {
		Game g = new Game();
	}
}

 

 

  main메서드에 Game객체를 생성한다면 에러가 날 것이다. 추상 클래스는 추상클래스만으로 객체를 생성할 수 없다. 추상클래스의 용도는 다른 클래스에게 영향을 주기 위함이다.

 

 

  추상클래스는 상속을 통해 미완성된 부분을 다시 완성시켜줘야 한다.

 

class GoldGamer extends Game{
	@Override //추상메서드 구현
	void play(int pos) {  
		if(pos==1) {
			
		}
	}
	@Override //추상메서드 구현
	int score() {
		return 0;
		/*
		 * skip
		 */
	}
}

 

  GoldGamer는 abstract class Game을 상속받아 추상클래스이지만, 상속받은 추상메서드들을 오버라이딩하여 완성된 클래스로 되었다.

  추상클래스로부터 상속받아 완성된 클래스로 만들기 위해서는 추상클래스의 추상 메서드 멤버들을 전부 다 오버라이딩해야한다.

abstract class SilverGamer extends Game{
	@Override
	int score() {
		return -1;
	}
}

  SilverGamer클래스는 추상클래스 Game에 모든 멤버를 오버라이딩하지 않아 미완성 클래스이다. 그래서 객체 생성이 불가능해진다.

 

 

public class ArrayListEx1 {
	public static void main(String[] args)throws IOException {
		GoldGamer g = new GoldGamer();
	}
}

완성된 클래스가 된 GoldGamer는 객체를 만들어질 수 있게 된다.

 

 


 

 

추상메서드

 

  구현부 {}가 없는 메서드이다. 

abstract 리턴타입 메서드이름();

 

  

  기존 메서드는 선언부와 구현부({})로 구성되어 있었지만, 추상메서드는 구현부가 없는 메서드이다. 

  

  미완성으로 만들어 놓은 이유는 메서드의 내용이 상속받는 클래스에 따라 달라질 수 있기 때문이다. 추상클래스를 상속받은 클래스에서 구현하도록 비워 두는 것이다. 이와 같이 메서드 구현부를 비워두면 상황에 따라 메서드를 적절히 구현해 줄 수 있다. 

 

  위에서 언급된 적 있지만, 모든 추상메서드를 오버라이딩을 해줘야 추상클래스로 부터 상속을 받고 사용할 수 있다. 

 


 

 

  여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하기도 하고, 기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어 상속하도록 하는 경우가 있다.

 

  상속은 자손 클래스를 만드는데 조상 클래스를 사용하는 것이다. 반대로 추상화는 기존의 클래스의 공통부분을 뽑아서 조상 클래스를 만드는 것이다. 

 

  즉, 상속은 이미 만들어진 조상클래스를 씨를 뿌리는 자손을 만들어주는 데 추상화는 자손들이 조상을 만들어주는 것과 비슷하다.

 

  상속계층도를 따라 내려갈수록(조상-> 자손) 클래스는 점점 기능이 추가되어 구체화의 정도가 심해져 복잡해진다. 

  상속계층도를 따라 올라가면(자손-> 조상) 클래스는 추상화의 정도가 심해진다고 할 수 있다.

 

  즉, 상속계층도를 내려 갈수록 세분화되며, 복잡해진다. 반대로 올라갈수록 공통 요소만 남아 간결해진다.  

 

 

 


 

  추상클래스의 효과를 보여주는 프로그램

 

public class AbstractClass {
	public static void main(String[] args) {
		Cars[] cars = { new BMW(), new Hyundai(), new BMW() };
		for (int i = 0; i < cars.length; i++) {
			cars[i].doors_Check(4);
		}
	}
}

abstract class Cars {
	int doors = 0;
	String car_Name = "";
	int since = 0;

	abstract void doors_Check(int doors);

	abstract void name_Check(String car_Name);
}

class BMW extends Cars {
	void doors_Check(int doors) {
		System.out.println("(BMW)이 차의 문의 개수는: " + doors + "입니다.");
	}

	void name_Check(String car_Name) {
		System.out.println("이 차의 이름은: " + car_Name);
	}
}

class Hyundai extends Cars {
	void doors_Check(int doors) {
		System.out.println("(Hyundai)이 차의 문의 개수는: " + doors + "입니다.");
	}

	void name_Checked(String car_Name) {
		System.out.println("이 차의 이름은: " + car_Name);
	}
}

 

  abstract 클래스를 구현하기 위해서는 상속을 받은 자손클래스를 이용해  구현을 해줘야 한다. 여기서 추상클래스는 항상 조상이므로, 다형성 조건에 맞는다. 조상타입의 참조변수로 자손 타입의 객체를 참조시키는 것이 가능하다. 

  즉, Cars 객체 배열에 자손 타입의 객체를 생성할 수 있어, 숫자가 많아도 단 한 줄의 코드로 커버가 가능하다. 

 

  만약 Cars 대신 최고 조상인 Object 객체배열을 생성해 BMW, Hyundai 객체를 담는다고, doors_Check메서드를 사용한다면 에러가 발생할 것 이다. 이유는 Object로 객체배열을 생성해 다형성을 이용해 객체를 생성할 수는 있지만. Object에는 없는 doors_Check 메서드를 호출하는 것은 불가능하기 때문이다.

 

 

  객체배열은 쉽게 생각하면 참조변수들을 묶어 놓은 데이터 집합이라고 볼 수 있다.

 

 

'Java > OOP' 카테고리의 다른 글

[Java] instanceof 연산자  (0) 2022.03.20
[Java] 참조변수의 형변환  (0) 2022.03.15
[Java] 다형성  (0) 2022.03.04
[Java] 접근 제어자 (access modifier)  (0) 2022.02.20
[Java] static, final, abstract의 정의  (0) 2022.02.18
Comments