개발일지/Java

Java 추상화 (Abstraction)

E-room 2022. 9. 12. 15:51
728x90
기존 클래스들의 공통적인 요소들을 뽑아 상위 클래스를 만들어 내는 것

오토바이^^

 

abstract 제어자

주로 클래스와 메서드를 형용하는 키워드

  • 클래스 앞에 붙은 경우 : 추상 클래스
  • 메서드 앞에 붙은 경우 : 추상 메서드
  • 어떤 클래스에 추상 메서드가 포함되어있는 경우 해당 클래스는 자동으로 추상 클래스가 된다
  • 미완성이라는 의미
  • 객체 생성이 불가
abstract class AbstractExample { // 추상 메서드가 최소 하나 이상 포함돼있는 추상 클래스
	abstract void start(); // 메서드 바디가 없는 추상메서드
}
AbstractExample abstractExample = new AbstractExample(); // 에러발생.

 

추상 클래스

메서드 시그니처만 존재하고 바디가 선언되지 않은 추상 메서드를 포함하는 '미완성 설계도'

 

  • 상속 관계에 있어 새로운 클래스를 작성하는데 유용하다
  • 상위 클래스에서 선언부만 작성하고, 실제 구체적인 내용을 하위 클래스에서 구현하도록 비워두어 설계가 변하는 상황이 오더라도 유연하게 대응이 가능하다
  • 상층부에 가까울수록 더 공통적인 속성과 기능들이 정의되어 있다
abstract class Animal {
	public String kind;
	public abstract void sound();
}

class Dog extends Animal { // Animal 클래스로부터 상속
	public Dog() {
		this.kind = "포유류";
	}

	public void sound() { // 메서드 오버라이딩 -> 구현부 완성
		System.out.println("멍멍");
	}
}

class Cat extends Animal { // Animal 클래스로부터 상속
	public Cat() {
		this.kind = "포유류";
	}

	public void sound() { // 메서드 오버라이딩 -> 구현부 완성
		System.out.println("야옹");
	}
}

class DogExample {       
    public static void main(String[] args) throws Exception {
       Animal dog = new Dog();
       dog.sound();

       Cat cat = new Cat();
       cat.sound();
    }
 }

// 출력값
멍멍
야옹

 

final 키워드

더 이상 변경이 불가능하거나 확장되지 않는 성질을 갖게 한다

위치 의미
클래스 변경 또는 확장 불가능한 클래스, 상속 불가
메서드 오버라이딩 불가
변수 값 변경이 불가한 상수
final class FinalEx { // 확장/상속 불가능한 클래스
	final int x = 1; // 변경되지 않는 상수

	final int getNum() { // 오버라이딩 불가한 메서드
		final int localVar = x; // 상수
		return x;
	}
}

 

 

인터페이스

  • 추상 메서드의 집합

- 기본 구조

  • class 키워드 대신 interface 키워드 사용
  • 내부의 모든 필드가 public static final로 정의된다 (생략 가능)
  • static과 default 메서드 이외에 모든 메서드가 public abstract로 정의된다 (생략 가능)
public interface InterfaceEx {
    public static final int rock =  1; // 인터페이스 인스턴스 변수 정의
    final int scissors = 2; // public static 생략
    static int paper = 3; // public & final 생략

    public abstract String getPlayingNum();
		void call() //public abstract 생략 
}

 

- 구현

extends 대신 implements 사용

 

특정 인터페이스를 구현한 클래스는 해당 인터페이스에 정의된 모든 추상 메서드를 구현해야 한다

-> 인터페이스가 가진 모든 추상 메서드들을 해당 클래스 내에서 오버 라이딩하여 바디를 완성해야 한다

class 클래스명 implements 인터페이스명 {
    ... // 인터페이스에 정의된 모든 추상메서드 구현
}

 

- 다중 구현

클래스 간의 상속은 다중 상속이 허용되지 않지만

인터페이스는 다중 구현이 가능하다

-> 애초에 미완성된 멤버를 가지고 있기 때문에 충돌이 발생할 여지없이 안전하게 구현이 가능하기 때문

class ExampleClass implements ExampleInterface1, ExampleInterface2, ExampleInterface3 { 
				... 생략 ...
}

 

- 장점

  • 역할과 구현을 분리시켜 복잡한 구현의 내용 또는 변경과 상관없이 해당 기능을 사용할 수 있다
  • 코드 변경의 번거로움을 최소화하고 손쉽게 해당 기능을 사용할 수 있다
  • 독릭접인 프로그래밍을 통해 한 클래스의 변경이 다른 클래스에 미치는 영향을 최소화할 수 있다
interface Customer {
  String getOrder();
}

class CafeCustomerA implements Customer {
  public String getOrder(){
		return "a glass of iced americano";
	}
}

class CafeCustomerB implements Customer {
  public String getOrder(){
		return "a glass of strawberry latte";
	}
}

class CafeOwner {
  public void giveItem(Customer customer) {
    System.out.println("Item : " + customer.getOrder());
  }
}

public class OrderExample {
    public static void main(String[] args) throws Exception {
        CafeOwner cafeowner = new CafeOwner();
        Customer cafeCustomerA = new CafeCustomerA();
        Customer cafeCustomerB = new CafeCustomerB();

        cafeowner.giveItem(cafeCustomerA);
        cafeowner.giveItem(cafeCustomerB);
    }
}

// 출력값
Item : a glass of iced americano
Item : a glass of strawberry latte

 

728x90