본문 바로가기
Language/Java

[Java] 자바기초 - 추상클래스와 인터페이스(abstract/interface)

by J4J 2020. 12. 21.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 추상 클래스와 인터페이스에 대해 적어보는 시간을 가져보려고 합니다.

 

사용 이유

 

추상 클래스와 인터페이스를 사용하는 이유는 클래스를 작성할 때 사용 용도에 맞는 필수적인 요소들을 포함시키기 위해 사용합니다.

 

예를 들어 핸드폰을 만들 때 핸드폰에는 필수적으로 알람 소리, 벨소리 등이 포함되는데 알람 소리와 벨소리들에 대해 정의하는 것을 포함시키지 않고 핸드폰 제작하는 것을 방지하기 위해 사용합니다.

 

이처럼 프로그래밍을 할 때도 A라는 클래스를 만들 때 클래스에 필요한 메서드들을 사전에 모두 정의하여 A클래스를 작성할 때 필수적인 메서드들 모두 정의할 수 있도록 도와줍니다.

 

 

추상 클래스

 

추상 클래스는 일반 클래스와 달리 abstract라는 키워드를 이용하여 클래스를 작성합니다.

 

그리고 메서드를 작성할 때 선언과 동시에 내용물을 정의하는 일반 클래스들과는 달리 선언까지만 한 추상 메서드들을 포함하고 있습니다.

 

추상 클래스는 아래 코드와 같이 작성할 수 있습니다.

 

package abstract_interface;

public abstract class AbstractPhone {
	
	int intVal; // 일반 변수
	
	public void alarm() { // 일반 메서드
		System.out.println("띠리리리리리링");
	}
	
	public abstract void bell(); // 추상 메서드
}

 

 

위의 코드처럼 일반 클래스와 같이 변수를 선언해 둘 수 있고 메서드도 정의할 수 있지만 메서드 앞에 abstract라는 키워드를 붙인 추상 메서드를 포함시킬 수도 있습니다.

 

그럼 이렇게 선언된 추상 클래스를 어떻게 사용할까요?

 

다음 코드를 봅시다.

 

package abstract_interface;

public class Phone1 extends AbstractPhone {
	
	@Override
	public void bell() {
		System.out.println("또로로로로로로롱");
	}
	
	public static void main(String[] args) {
		Phone1 phone1 = new Phone1();
		phone1.alarm(); // 띠리리리리리링
		phone1.bell(); // 또로로로로로로롱
		
		phone1.intVal = 32;
		System.out.println(phone1.intVal); // 32
	}
}

 

 

추상 클래스는 상속에 사용되는 extends라는 키워드를 통해 사용될 수 있습니다.

 

일반 클래스에서는 메서드들이 모두 정의가 되어야 하기 때문에 선언만 되어 있던 bell() 메서드를 정의해야만 하고 이미 정의되어 있던 alarm() 메서드는 정의하지 않고 사용할 수 있습니다.

 

또한 일반 클래스와 동일하게 변수도 값을 넣은 뒤 사용할 수 있습니다. (abstract 키워드는 변수에 사용 못합니다.)

 

 

인터페이스

 

인터페이스도 추상 클래스와 유사하지만 추상 클래스와 달리 메서드를 정의하지 못하기 때문에 추상 메서드만 사용할 수 있습니다.

 

즉, 모든 메서드들이 선언만 되어야 한다는 의미입니다.

 

아래 코드를 확인해봅시다.

 

package abstract_interface;

public interface InterfacePhone {
	
	int intVal = 32; // public static final int intVal = 32, 상수
	
	public void alarm(); // 추상 메서드
	
	public abstract void bell(); // 추상 메서드
}

 

 

위의 코드처럼 abstract class대신에 interface라는 키워드를 이용하여 인터페이스를 작성할 수 있습니다.

 

그리고 말씀드린 것처럼 메서드들이 모두 추상 메서드이기 때문에 abstract키워드를 사용 안 해도 추상 메서드로 인식합니다.

 

또한 상수값만 사용이 가능하며 public static final을 생략하고 작성해도 자동으로 입력이 됩니다.

 

이렇게 정의된 인터페이스를 사용해봅시다.

 

 

728x90

 

 

package abstract_interface;

public class Phone2 implements InterfacePhone {
	
	@Override
	public void alarm() {
		System.out.println("띠라띠라띠라디라띠라");
	}
	
	@Override
	public void bell() {
		System.out.println("또로로로멘또롱");
	}
	
	public static void main(String[] args) {
		Phone2 phone2 = new Phone2();
		phone2.alarm(); // 띠라띠라띠라디라띠라
		phone2.bell(); // 또로로로멘또롱
		
		System.out.println(Phone2.intVal); // 32
	}
}

 

 

인터페이스는 추상 클래스와 달리 extends를 사용하지 않고 implements라는 키워드를 사용합니다.

 

인터페이스에 선언된 메서드들을 모두 정의해줘야 메서드들을 사용할 수 있고 상수는 static으로 선언된 상수값이기 때문에 phone2라는 인스턴스 대신에 클래스 자체인 Phone2를 통해 사용될 수 있습니다.

 

 

구분 이유

 

코드들을 확인해보면 추상 클래스든 인터페이스든 사용 방법은 비슷하다는 것을 확인하실 수 있을 겁니다.

 

그럼 이 둘을 구분한 이유가 무엇일까요?

 

그 이유는 다중 상속 때문입니다.

 

추상 클래스는 단일 상속만 가능, 인터페이스는 다중 상속까지 가능. 정말 쉽죠?

 

말 그대로 추상 클래스는 하나의 부모만 상속을 받을 수가 있는데 그 이유를 아래 코드로 보여드리겠습니다.

 

package abstract_interface;

public abstract class AbstractClass1 {
	
	public void output1() {
		System.out.println("AbstractClass1의 출력물입니다.");
	}
	
	public abstract void output2();
}

 

package abstract_interface;

public abstract class AbstractClass2 {
	
	public void output1() {
		System.out.println("AbstractClass2의 출력물입니다.");
	}
	
	public abstract void output2();
}

 

 

위의 코드처럼 만약 하나의 클래스가 위에 정의된 두 추상 클래스를 상속받는다고 할 때 output의 결과물은 무엇이 나와야 될까요?

 

명확하게 무엇이 나와야 되는지 결론을 내릴 수가 없고 이런 일들을 방지하고자 자바에서는 다중 상속을 금지시켰습니다.

 

하지만 코드를 작성하다 보면 다중 상속이 필요한 데 그럴 때 인터페이스를 사용하게 되는 겁니다.

 

인터페이스도 우선 코드를 확인해 봅시다.

 

package abstract_interface;

public interface Interface1 {
	
	public void output1();
	
	public abstract void output2();
}

 

package abstract_interface;

public interface Interface2 {
	
	public void output1();
	
	public abstract void output2();
}

 

package abstract_interface;

public class MainClass implements Interface1, Interface2 {
	
	@Override
	public void output1() {
		System.out.println("output1의 출력물입니다.");
	}
	
	@Override
	public void output2() {
		System.out.println("output2의 출력물입니다.");
	}
	
	public static void main(String[] args) {
		MainClass mainClass = new MainClass();
		
		mainClass.output1(); // output1의 출력물입니다.
		mainClass.output2(); // output2의 출력물입니다.
	}
}

 

 

이처럼 인터페이스는 똑같은 메서드명을 선언하더라도 정의하지 않았기 때문에 다중 상속을 받더라도 서로 구분될 필요가 없습니다.

 

추상 클래스가 해주지 못하는 다중 상속을 인터페이스가 해줌으로 써 추상화를 위해 사용된다는 공통점을 가지고 있음에도 불구하고 구분되어 사용이 되는 것입니다.

 

 

정리

 

추상 클래스와 인터페이스는 사용 용도에 맞는 필수 요소들을 포함하기 위해 사용 (추상화)
추상 클래스는 abstract 키워드를 이용, 인터페이스는 interface 키워드를 이용
추상 클래스는 변수 선언, 메서드 정의 가능 / 인터페이스는 상수, 메서드 선언만 가능
추상클래스는 단일 상속만 가능, 인터페이스는 다중 상속도 가능

 

 

 

이상으로 추상 클래스와 인터페이스에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

728x90
반응형

댓글