객체지향 프로그래밍 추상화와 다형성

Sitehyun·2023년 1월 4일
0

IT Log

목록 보기
7/10

원래 커피를 마시면 울렁거리는 체질이라 커피를 못마셨는데 요즘 한 잔씩 몸이 받기 시작했다.

나도 이렇게 카페인의 길로 들어서는 것인가?


추상화

먼저 '추상'이란 단어를 생각해보자 여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용. 이라고 네이버 사전이 알려줬다.

그렇다면 프로그래밍에서 말하는 추상화란? 객체의 공통되는 특성이나 속성 따위를 추출하는 것 일 것이다.

기존에 공부했던 상속은 기존에 있던 클래스의 속성과 기능을 재사용하기위해 extends키워드를 사용하여 확장해주고 하위 클래스에서 그 기능과 속성을 사용할 수 있게하였다.

나는 추상화도 상속과 비슷한 갈래에 속한다고 생각한다. 이 글을 쓰는 지금 개념의 혼동이와 추상화와 상속의 다른점은 뭐지... 하고 생각하였다.

그래서 나온 결론은 상속과 추상화의 다른점은 그 목적성에 있다고 생각한다. 상속은 기존의 코드를 확장하여 사용한다. 라는 것에 중점을 두었다면 추상화는 그 객체들의 공통점을 추출하여 다루기 쉽게하기 위해라는 것에 목적성이 있다고 생각한다.

abstract 제어자

abstract제어자는 일전에 배웠던 접근제어자(private, public...etc)와 다른 기타 제어자에 속해있다.

abstract는 영어로 추상적인 이라는 의미를 가지고있다. 자바 프로그래밍의 관점에서 내포하는 의미는 미완성이라 정의할 수 있다.

abstract제어자는 주로 클래스와 메서드를 꾸며주는 역할을 하며, 메서드 앞에 붙은 경우 추상메서드, 클래스 앞에 붙은 경우 추상 클래스라 명명한다. 또한 어떠한 클래스에 추상메서드를 포함하고 있는 경우 해당 클래스는 자동으로 추상 클래스가 된다.

abstract class AbstractExample{  // 추상메서드가 하나 이상 포함되어 있는 추상클래스 
	
    abstract void start();  // 메서드 바디가 없는 추상 메서드 
}

abstract의 가장 핵심적인 개념은 미완성이다.
추상 메서드는 메서드의 시그니쳐만 존재하고 바디는 존재하지 않는다.

마지막으로 추상 클래스는 미완성의 설계도이기 때문에 메서드 바디가 완성 되기 전까지 이를 기반으로 객체 생성이 불가능하다.

추상 클래스

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();
    }
 }

// 출력값
멍멍
야옹

위의 코드를 보시면 Animal 추상 클래스 안에 미완성의 메서드 sound가 있습니다. 그리고 이 추상 클래스를 상속받은 DogCat에서 미완성의 메서드를 오버라이딩하여 완성하였습니다.

메인 메서드에서 Animal타입의 참조 변수를 선언하여 각각 Dog타입, Cat타입의 생성자를 참조해줍니다. 그 결과 출력값으로 각각 멍멍과 야옹이 출력되었습니다.

추상 클래스를 사용하면 상속을 받는 하위 클래스에서 오버라이딩을 통해 각각 상황에 맞는 메서드 구현이 가능하다는 장점이 있습니다.

인터페이스

추상 클래스는 메서드 바디가 없는 추상 메서드를 하나 이상 포함한다는 점 외에는 기본적으로 일반 클래스와 동일하다고 할 수 있습니다.

반면 인터페이스는 기본적으로 추상 메서드와 상수만을 멤버로 가질 수 있다는 점에서 추상 클래스에 비해 추상화 정도가 더 높다고 할 수 있습니다.

인터페이스 기본 구조

인터페이스를 작성하는 것은 기본적으로 클래스를 작성하는 것과 유사합니다. class키워드 대신 interface키워드를 사용합니다.

일반 클래스와 다르게, 내부 모든 필드가 public static fianl로 정의되고 default, static메서드 이외 모든 메서드가 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 인터페이스명 {
		... // 인터페이스에 정의된 모든 추상메서드 구현
}

또한 인터페이스는 추상 클래스, 상속과 다르게 다중 상속이 가능합니다. 추상클래스 + 인터페이스 조합으로도 사용이 가능합니다.

인터페이스의 장점

public class InterfaceExample {
    public static void main(String[] args) {
        User user = new User(); // User 클래스 객체 생성
        user.callProvider(new Provider()); // Provider 객체 생성 후에 매개변수로 전달
    }
}

class User { // User 클래스
    public void callProvider(Provider provider) { // Provider 객체를 매개변수로 받는 callProvider 메서드
        provider.call();
    }
}

class Provider { //Provider 클래스
    public void call() {
        System.out.println("무야호~");
    }
}

// 출력값
무야호~

위으 코드에서 User클래스는 Provider클래스에 의존하고 있습니다. 이 상황에서 Provider코드에 이상이 생겨 교체를 해야한다면 User클래스의 callProvider의 매개변수 수정, 그리고 이를 호출하는데 사용되는 new Provider수정 을 거쳐야합니다.

짧은 코드이기에 2개의 변경점에 그치겠지만 수 만, 수 백만 줄의 코드에서 이런 일이 발생한다면 참사나 다름없죠.


이럴때 인터페이스를 사용한다면 인터페이스 Cover를 구현하는 ProviderProvider2 를 같은 타입인 Cover타입으로 사용할 수 있습니다. 이는 다형성과도 깊은 연관이 있습니다.

Provider3클래스를 만들게 되더라도 Cover를 구현한다면 User클래스는 수정할 필요가 사라집니다.

다형성

자바 프로그래밍에서 다형성은 한 타입의 참조변수를 통해 여러 타입의 객체를 참조할 수 있도록 만든 것입니다.

앞서 위 인터페이스에서 ProviderProvider2는 엄연히 다른 클래스이지만 Cover를 구현해줌으로서 Cover타입의 참조변수에 두 타입의 객체를 참조할 수 있도록 허용했습니다.

앞서 배운 상속도 다형성을 내포하고있습니다.

pill, json, nati 는 각각 Person, Programmer, Dancer라는 타입을 가지고있으나 Person이라는 타입의 참조변수에 참조가 될 수 있습니다.

jake의 경우 생성될 때 하위의 타입의 참조변수에는 상위 타입을 참조할 수 없습니다.

(Programmer)를 넣어 강제 형변환을 해주어야 참조가 가능합니다.

반면에 하위타입에서 상위로 넘어갈 때는 강제형변환이 필요하지 않습니다.

0개의 댓글

관련 채용 정보