본문 바로가기

Java

[Java] 24

추상 클래스

- 추상메소드가 있는 클래스

- 필드 위에 미구현된 공간이 존재한다.(추상 메소드 부분이 미구현된 상태)

추상 클래스를 상속 받은 클래스

1. 반드시 추상 메소드를 override 해야한다.

2. 자식 클래스도 추상 클래스로 만든다.

추상 클래스 사용 목적

- 자식 클래스에서 반드시 재정의되어야 하는 메소드를 추상 메소드로 선언함으로써 강제성을 부여할 수 있다.

추상 메소드

- 이름만 정의된 메소드

- 기능은 미구현 상태 body( { } )가 없다

인터페이스(틀)

- 추상 클래스를 고도화시킨 문법

- 추상 메소드만 선언할 수 있다.

- 상속 방법 : implements로 상속을 받는다.

- 한 번 밖에 사용하지 못하는 extends를 아낄 수 있다.

자바에서는 모호성이 발생할 수 있기 때문에 원칙적으로 다중 상속을 허용하지 않는다.

하지만 인터페이스의 등장으로 여러개의 인터페이스를 상속 받을 수 있게 되었고, 사실상 다중 상속을 허용하고 있다.

어댑터 클래스

- 인터페이스에서 몇 가지만 override 하고 싶을 때는 adapter 클래스를 활용할 수 있다.

- adapter 클래스는 인터페이스의 추상 메소드를 구체화 시켜 놓은 클래스로서,

   adapter 클래스를 상속 받은 클래스는 원하는 메소드만 구체화 해도 객체화가 가능하다.

- 통상적으로 두 개 이상의 메소드가 있는 인터페이스는 짝꿍인 어댑터 클래스가 만들어져있다.

 

 

 

실습(추상 클래스와 추상 메소드)

1. 부모 클래스(Parent.java) 생성

// 추상 클래스
public abstract class Parent {

	public void normalFunction() {
		System.out.println("일반 메소드");
	}
	
	// 추상 메소드
	public abstract void abstractFunction();
	
}

 

2. 자식 클래스(Child.java) 생성

public class Child extends Parent{

	@Override
	public void abstractFunction() {
		System.out.println("자식에서 오버라이딩된 추상 메소드");
	}

}

 

3. Main.java에서 실행

public class Main {
	public static void main(String[] args) {

//      Parent p = new Parent();  // 추상 클래스는 객체화가 불가능하다.(미구현된 공간이 남아있기 때문)
		
        Child c = new Child();  // 자식에서 오버라이딩해야 객체화가 가능하다.

        c.normalFunction();
        c.abstractFunction();

	}
}

 

결과

 

실습(인터페이스)

1. 인터페이스(Soldier.java) 생성

public interface Soldier {
	
	int num = 10;  // 오로지 static final 변수만 넣을 수 있기 때문에 static final 이 생략되었다.
	static final int num2 = 10;  // final : 변수의 값을 변경하지 못하도록 상수화하는 키워드
	
	// 인터페이스는 오로지 추상 메소드만 선언이 가능하다.
	// 오직 추상 메소드만 선언이 가능하기 때문에 abstract는 생략 가능하다.
	public void eat();
	public abstract void sleep();
	public abstract void work();
	
}

 

2. 인터페이스를 상속받는 클래스(Corporal.java) 생성

public class Corporal implements Soldier {

	@Override
	public void eat() {
		System.out.println("밥을 많이 잘 먹는다.");
	}

	@Override
	public void sleep() {
		System.out.println("잠을 잘 잔다.");
	}

	@Override
	public void work() {
		System.out.println("일을 잘한다.");
	}

}

 

3. 인터페이스를 상속받는 클래스(SecondMan.java) 생성

public class SecondMan implements Soldier{

	@Override
	public void eat() {
		System.out.println("밥이 잘 넘어가지 않는다.");
	}
	
	@Override
	public void sleep() {
		System.out.println("잠이 잘 오지 않는다.");
	}
	
	@Override
	public void work() {
		System.out.println("일을 열심히 하기는 하지만 잘 못한다.");
	}
	
}

 

4. 인터페이스를 상속받는 부모 클래스(SoldierAdapter.java) 생성

public class SoldierAdapter implements Soldier {

	@Override
	public void eat() {;}

	@Override
	public void sleep() {}

	@Override
	public void work() {}

}

 

5. 자식 클래스(Sergeant.java) 생성

public class Sergeant extends SoldierAdapter {

	@Override
	public void sleep() {
		System.out.println("잠을 너무 많이 잔다.");
	}

}

 

6. Main.java에서 실행

public class Main {
	public static void main(String[] args) {

//		Soldier s = new Soldier();  // 객체화가 불가능하다.(미구현된 상태 존재)
		SecondMan sm = new SecondMan();
		Corporal c = new Corporal();
		Sergeant s = new Sergeant();
		
		Soldier[] ar = {sm, c, s};
		
		for(int i = 0; i < ar.length; i++) {
			if(!(ar[i] instanceof SoldierAdapter)) {
				ar[i].eat();
			}
		}
		
		System.out.println(sm instanceof Soldier);
		System.out.println(c instanceof Soldier);
		
		Soldier s1 = sm;
		Soldier s2 = c;
		
		if(!(s instanceof SoldierAdapter)) {
			s.eat();
		}
		
		sm.eat();
		sm.work();
		sm.sleep();
		
		c.eat();
		c.work();
		c.sleep();
		
	}
}

 

결과

 

 

'Java' 카테고리의 다른 글

[Java] 26  (0) 2022.01.26
[Java] 25  (0) 2022.01.25
[Java] 23  (0) 2022.01.23
[Java] 22  (0) 2022.01.22
[Java] 21  (0) 2022.01.21