추상 메소드와 추상 클래스
선언되어 있지만 구현되지 않은 메소드, abstract로 선언
public abstract String getName();
public abstract void setName(String s);
2가지 종류의 추상 클래스 사례
추상 메소드를 하나라도 가진 클래스
클래스 앞에 반드시 abstract라고 선언해야 한다.
추상 메소드를 포함하는 추상 클래스
abstract class Shape {
public Shape() {
public void paint() { draw();}
abstract public void draw();
}
추상 메소드가 하나도 없지만 abstract로 선언된 클래스
추상 메소드가 없는 추상 클래스
abstract class MyComponent {
String name;
public void load(String name) {
this.name = name;
}
}
추상 클래스는 객체를 생성할 수 없다.
abstract class Shape {
...
}
public class AbstractError {
public static void main(String[] args) {
Shape shape;
shape = new Shape(); // 컴파일 오류. 추상 클래스 Shape의 객체를 생성할 수 없다.
...
}
}
추상 클래스의 상속
부모클래스(추상 클래스)에 추상 메소드가 있을 때
- 자식클래스에서 추상메소드를 구현하지 않은 경우 추상메소드가 상속되어 자식클래스에 추상인 상태로 남기에 자식클래스도 추상클래스여야 한다.(abstract 선언)
abstract class Shape { // 추상클래스
public Shape() {}
public void pain() {draw;}
abstract public void draw(); // 추상메소드
}
abstract class Line extends Shape { // 추상클랫. draw()를 상속받기 때문이다.
public String toString() {return "Line";}
}
자식 클래스에서 추상메소드를 구현한 경우
- 자식클래스에서는 더이상 추상 메소드가 아님(오버라이딩), 그러므로 자식클래스는 추상클래스가 아니다. 일반 클래스로 승격
추상 클래스의 용도
설계와 구현 분리
슈퍼 클래스에서는 개념 정의
- 서브 클래스마다 다른 구현이 필요한 메소드는 추상 메소드로 선언
각 서브 클래스에서 구체적 행위 구현
- 서브 클래스마다 목적에 맞게 추상 메소드를 다르게 구현
계층적 상속 관계를 갖는 클래스 구조를 만들 때 사용한다.
추상 클래스의 구현 연습
public class GoodCalc extends Calculator {
@Override
public abstract int add(int a, int b) {
return a + b;
}
@Override
public abstract int subtract(int a, int b) {
return a - b;
}
@Override
public abstract double average(int[] a) {
sum = 0;
for(int i=0; i<a.length; i++) {
sum += a[i];
return sum/a.length;
}
public static void main(String[] args) {
GoodCalc c = new GoodCalc();
System.out.println(c.add(2, 3));
System.out.println(c.subtract(2,3));
System.out.println(c.average(new int[] {2, 3, 4}));
}
}
자바의 인터페이스
클래스가 구현해야 할 메소드들이 선언되는 추상형
인터페이스 선언
interface 키워드로 선언, 인터페이스에는 필드(멤버 변수) 선언 불가, 상수 선언 가능, 추상 메소드 선언 가능
public interface AudioClip {
public abstract void play();
인터페이스 구성 요소들의 특징
public 구성 요소
- 상수 - public static final 생략 가능
추상 메소드
- public abstract 생략 가능
- 인터페이스를 구현하는 클래스에서 오버라이드 해야 함
default 메소드
- Java 8부터 사용 가능
- public 생략 가능
- 인터페이스에 기본 구현코드가 작성되어 있음
- 인터페이스를 구현하는 클래스에서 오버라이드 하지 않아도 된다.
나머지 구성 요소
- Java 9부터 사용 가능
static 메소드
- public, private 모두 지정 가능. 생략하면 public만 사용한다.
- 인터페이스의 이름, 메소드 이름()의 형태로 호출 가능하다.
- 인터페이스 내의 다른 메소드에 의해 호출 가능
private 메소드
- 인터페이스 내에 메소드 코드가 작성되야 한다.
- 인터페이스 내부에서만 호출 가능
자바 인터페이스의 전체적인 특징
인터페이스의 객체 생성 불가능
new PhoneInterface(); // 오류, 인터페이스 객체 생성 불가능
인터페이스 타입의 레퍼런스 변수 선언 가능
PhoneInterface galaxy; // galaxy는 인터페이스에 대한 레퍼런스 변수
인터페이스 구현 - 인터페이스를 상속받는 클래스는 인터페이스의 모든 추상 메소드를 반드시 구현해야 한다.
인터페이스 사이의 상속 가능 - 인터페이스 사이에서는 다중 상속이 가능하다.
인터페이스 구현
인터페이스의 추상 메소드를 모두 구현한 클래스 작성 - implements 키워드 사용, 여러 개의 인터페이스 동시에 구현 가능
class SamsungPhone implements PhoneInterfare { // 인터페이스 구현
// PhoneInterface의 모든 추상메소드 구현
public void sendCall() {System.out.println("띠리리리링");}
public void receiveCall() {System.out.println("전화가 왔습니다.");}
// 메소드 추가 작성
public void flash() {System.out.println("전화기에 불이 켜졌습니다.");}
}
SamsungPhone 클래스는 PhoneInterface의 default 메소드 상속
다중 인터페이스 상속
extends 키워드 이용
interface MobilePhoneInterface extends PhoneInterface {
void sendSMS(); // 새로운 추상 메소드 추가
void receiveSMS(); // 새로운 추상 메소드 추가
}
다중 인터페이스 상속
interface MP3Interface {
void play(); // 추상 메소드
void stop(); // 추상 메소드
}
interface MusicPhoneInterface extends MobilePhoneInterface, MP3Interface {
void playMP3RingTone(); // 새로운 추상 메소드 추가
}
다중 인터페이스 구현
클래스는 하나 이상의 인터페이스를 구현할 수 있다.
interface AIInterface {
void recognizeSpech(); // 음성 인식
void SynthesisSpeech(); // 음성 합성
}
class AIPhone implements MobilePhoneInterface, AIInterface {
// MobilePhoneInterface의 모든 메소드를 구현한다.
public void sendCall() {...}
public void receiveCall() {...}
public void sendSMS() {...}
public void receiveSMS() {...}
// AIInterface의 모든 메소드를 구현한다.
public void recognizeSpeech() {...} // 음성 인식
public void synthesisSpeech() {...} // 음성 합성
// 추가적으로 다른 메소드를 작성할 수 있다.
public int touch() {...}
}
추상 클래스와 인터페이스 비교
유사점
- 객체를 생성할 수 없고, 상속을 위한 슈퍼 클래스로만 사용, 클래스의 다형성을 실현하기 위한 목적
차이점