면접 준비 용 자바 개념 정리 3
2018-09-22
1. 추상 클래스
1-1. 추상 클래스 사용 이유
- 실체 클래스들의 공통된 필드와 메소드의 이름을 통일할 목적
- 실체 클래스를 작성할 때 시간을 절약할 수 있다.
1-2. 추상 클래스 선언
- 추상 클래스를 선언할 때는 absctract 키워드를 붙여야 한다. abstact를 붙이게 되면 new 연산자를 이용해서 객체를 만들지 못하고 상속을 통해 자식 클래스만 만들 수 있다.
- 추상 클래스도 일반 클래스와 마찬가지로 필드, 생성자, 메소드 선언을 할 수 있다. new 연산자로 직접 생성자를 호출 할 수는 없지만 자식 객체가 생성될 때 super(…)를 호출해서 추상 클래스 객체를 생성하므로 추상 클래스도 생성자가 반드시 있어야 한다.
- 추상 클래스를 설계할 때, 하위 클래스가 반드시 실행 내용을 채우도록 강요하고 싶은 메소드가 있을 경우, 해당 메소드를 추상 메소드로 선언하면 된다. 자식 클래스는 반드시 추상 메소드를 재정의(오버라이딩)해서 실행 내용을 작성해야 하는데, 그렇지 않으면 컴파일 에러가 발생한다. 이것이 추상 메소드의 위력이다.
- 자식 타입은 부모 타입으로 자동 타입 반환이 될 수 있고, 메소드가 재정의되어 있을 경우 재정의된 자식 메소드가 호출되는 상속의 특징이 그대로 적용된다.
public abstact class Animal {
public String kind;
public void breathe(){
System.out.println("숨을 쉰다");
}
public abstract void sound();
}
public Dog extends Animal {
public Dog(){
this.kind = "포유류";
}
@Override
public void sound(){
System.out.println("멍멍");
}
}
public class Example{
public static void main(String[] args){
Dog dog = new Dog();
dog.sound();
Animal animal = new Dog(); // 자동 타입 변환
animal.sound(); // 재정의한 메소드 호출
}
}
2. 인터페이스
- 자바에서 인터페이스는 객체의 사용 방법을 정의한 타입이다.
- 인터페이스 변수는 참조 타입이기 때문에 구현 객체가 대입될 경우 구현 객체의 번지를 저장한다.
- 인터페이스는 객체의 교환성을 높여주기 때문에 다형성을 구현하는 매우 중요한 역할을 한다.
- 인터페이스는 개발 코드와 객체가 서로 통신하는 접점 역할을 하며, 개발 코드가 인터페이스의 메소드만 호출하면 인터페이스는 객체의 메소드를 호출시킨다. 그렇기 때문에 개발 코드는 객체의 내부 구조를 알 필요가 없고 인터페이스의 메소드만 알고 있으면 된다.
- 인터페이스를 개발 코드와 객체 중간에 두는 이유는 개발 코드를 수정하지 않고, 사용하는 객체를 변경할 수 있도록 하기 위해서이다. 개발 코드 측면에서는 코드 변경 없이 실행 내용과 리턴값을 다양화 할 수 있다는 장점이 있다.
- 클래스는 필드, 생성자, 메소드를 구성 멤버로 가지는데 비해, 인터페이스는 상수와 메소드만을 구성 멤버로 가진다. 인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없다. 자바 7 이전까지는 인터페이스의 메소드는 실행 블록이 없는 추상 메소드로만 선언이 가능했지만 자바 8부터는 디폴트 메소드와 정적 메소드도 선언이 가능하다.
interface 인터페이스명 {
// 상수
타입 상수명 = 값;
// 추상 메소드
타입 메소드(매개변수, ...);
// 디폴트 메소드
default 타입 메소드(매개변수, ...){...}
// 정적 메소드
static 타입 메소드(매개변수, ...){...}
}
2-1. 상수 필드 선언
- 인터페이스는 상수 필드만 선언할 수 있다. 상수는 public static final로 선언하므로 인터페이스에 선언된 필드는 모두 public static final 특성을 갖는다.
- public, static, final을 생략하더라도 자동으로 컴파일 과정에서 붙게 된다.
2-2. 추상 메소드 선언
- 인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행된다.
- 인터페이스에 선언된 추상 메소드는 모두 public abstact의 특성을 갖기 때문에 public abstact를 생략하더라도 컴파일 과정에서 붙게 된다
2-3. 디폴트 메소드 선언
- 디폴트 메소드는 자바 8에서 추가되었다. 형태는 클래스의 인스턴스 메소드와 동일한데, default 키워드가 리턴 타입 앞에 붙는다. 디폴트 메소드는 public 특성을 갖기 때문에 public을 생략하더라도 자동으로 컴파일 과정에서 붙게 된다.
- 디폴트 메소드는 인터페이스에 선언되지만, 인터페이스에서 바로 사용할 수는 없다. 디폴트 메소드는 추상 메소드가 아닌 인스턴스 메소드이므로 구현 객체가 있어야 사용 할 수 있다.
- 디폴트 메소드는 인터페이스의 모든 구현 객체가 가지고 있는 기본 메소드라고 생각하면 된다. 그러나 어떤 구현 객체는 디폴트 메소드의 내용이 맞지 않아 수정이 필요할 수도 있다. 이 때는 디폴트 메소드를 재정의(오버라이딩)해서 자신에게 맞게 수정하면, 디폴트 메소드가 호출 될 때 자신이 재정의한 메소드가 호출된다.
[public] default 리턴타입 메소드명(매개변수, ...){}
2-4. 정적 메소드 선언
- 정적 메소드는 디폴트 메소드와 마찬가지로 자바 8에서 추가된 인터페이스의 새로운 멤버이다
- 형태는 클레스의 정적 메소드와 완전 동일하다
- 정적 메소드는 public 특성을 갖기 때문에 public을 생략하더라도 자동적으로 컴파일 과정에서 붙게 된다
[public] static 리턴타입 메소드명(매개변수, ...){}
2-5. 인터페이스 구현
- 인터페이스에 선언된 추상 메소드에 대응하는 실체 메소드를 구현 클래스가 작성하지 않으면 구현 클래스는 자동으로 추상 클래스가 된다. 그러므로 클래스 선언부에 abstact 키워드를 추가해야 된다.
public interface Computer {
void powerOn();
void powerOff();
default void passwordCheck(boolean check){
if(check){
System.out.println("바탕화면으로 이동")
} else {
System.out.println("암호가 틀렸습니다");
}
}
static void mute(){
System.out.println("음소거");
}
}
public Desktop implements Computer{
public void powerOn(){
System.out.println("전원 on");
}
public void powerOff(){
System.out.println("전원 off");
}
}
public class Example {
public static void main(String[] args){
Computer computer = new Desktop();
}
}
3. 익명 구현 객체
- 만약 일회성의 구현 객체를 만들어야 할 때, 소스 파일을 만들고 클래스를 선언하는 것은 비효율적이다. 자바는 소스 파일을 만들지 않고도 구현 객체를 만들 수 있는 방법을 제공하는데 이것이 바로 익명 구현 객체이다.
- 인터페이스 변수 = new 인터페이스() { // 인터페이스에 선언된 추상 메소드의 실제 메소드 선언 }
public class Example{
public static void main(String[] args){
Computer computer = new Desktop(){
public void PowerOn(){ System.out.println("전원 on") };
public void PowerOff(){ System.out.println("전원 off") };
}
}
}