11. 객체지향프로그래밍의 이해 / 20230426

2023. 4. 27. 00:06

🧑🏻‍💻 TIL(Today I Learned)


객체지향 프로그래밍에서 핵심을 담당하는 네 가지 중 두 가지 "다형성과 추상화"

 

1. 다형성(Polymorphsim)

➡️ 하나의 객체가 여러 가지 형태를 가질 수 있는 성질

➡️ 상위 클래스 타입 참조 변수로 하위 클래스 타입 객체를 다루는 것
    즉 상위 클래스 타입의 참조 변수를 통해서 하위 클래스의 객체를 참조할 수 있도록 허용한 것 

➡️ 하위 클래스의 참조 변수로 상위 클래스 타입의 객체를 가리킬 수 없음 

class Tv {
}

class SmartTv extends Tv {
}

Tv t = new Tv();
SmartTv s = new SmartTv(); // 원래는 이렇게 타입이 일치해야함

Tv t = new SmartTv(); 
// 다형성에서는 타입불일치도 오케이
// 부모 클래스의 참조 변수로 자식 클래스 객체 다루는 것 
// 참조변수가 사용할 수 있는 멤버의 개수는 상위 클래스의 멤버의 수 --> 사용할 수 있는 멤버가 줄어든다
📍 객체와 참조변수 타입이 일치할 때와 일치하지 않을 때의 차이? 
- 타입이 일치하지 않는 경우 참조 변수가 사용할 수 있는 멤버의 개수는 상위 클래스의 멤버의 수로 제한된다.
- > 서로 사용할 수 있는 멤버의 수가 달라짐 

 

🔎 참조 변수의 타입 변환 

➡️ 사용할 수 있는 멤버의 개수를 조절하는 것 

➡️ 조건 

  • 서로 상속 관계에 있는 상속 클래스 - 하위 클래스 사이에서만 타입 변환 가능
  • 하위 클래스 타입에서 상위 클래스 타입으로의 타입 변환(업캐스팅)은 형변환 연산자(괄호) 생략 가능
  • 상위 클래스에서 하위 클래스 타입으로 변환(다운캐스팅)은 형변환 연산자(괄호) 반드시 명시해야 함
    → 다운 캐스팅은 업 캐스팅이 되어 있는 참조 변수에 한해서만 가능

⭐️ 형변환을 하는 것은 좋지만 실제 인스턴스가 무엇인지 확인해야 함 그 인스턴스 수가 넘어가면 에러가 남! ⭐️

 

🔎 instanceof 연산자

➡️ 참조 변수의 타입 변환 즉, 캐스팅이 가능한지 여부를 boolean 타입으로 확인할 수 있는 것(가능하면 true 반환)
    → 형변환 전에 반드시 확인해야 함!

➡️ 캐스팅 가능 여부를 판단하기 위해서는 

  • 객체를 어떤 생성자로 만들었는가
  • 클랫 사이에 상속 관계가 존재하는가
참조_변수 instanceof 타입

// 결과값이 true : 참조 변수가 검사한 타입으로 타입 변환 가능
// 결과값이 false : 타입 변환 불가능
// 참조변수가 null 인 경우 : false 반환

➡️ 코드 규모가 커지면 확인하기가 어려우니 instanceof 연산자 제공함

 

🔎 매개변수의 다형성

➡️ 참조형 매개변수는 메서드 호출시 자신과 같은 타입 또는 자손 타입의 인스턴스를 넘겨줄 수 있음

➡️ 다형성의 장점 

  • 다형적 매개 변수 
  • 하나의 배열로 여러 종류 객체 다루기
public class PolymorphismEx {
  public static void main(String[] args) {
    Customer customer = new Customer();
    customer.buyCoffee(new Americano()); // 매개변수 호출시 하위 타입의 인스턴스 넣어주기
    customer.buyCoffee(new CaffeLatte());

    System.out.println("현재 잔액은 " + customer.money + "원 입니다.");
  }
}

 

 

2. 추상화(Abstract)

➡️ 자바에서 추상화는 객체의 공통적인 속성과 기능을 추출하여 정의하는 것

➡️ 기존 클래스들의 공통적인 요소를 뽑아서 상위 클래스를 만들어내는 것 

➡️ 코드의 중복을 줄이고 효과적으로 클래스 간의 관계 설정 가능, 유지보수 용이

➡️ ⭐️추상 클래스와 인터페이스로 추상화 구현

 

🔎 abstract 제어자

➡️ 사전적 '추상적인' / 자바에서는 '미완성'

➡️ 메서드 앞에 붙으면 추상메서드, 클래스 앞에 붙은 경우 추상 클래스 
     어떤 클래스에 추상 메서드가 포함되어 있다면 자동으로 추상 클래스가 됨

abstract class AbstractExample { // 추상 메서드가 최소 하나 이상 포함돼있는 추상 클래스
	abstract void start(); 
// 메서드 바디가 없는 추상메서드
// 메서드 시그니처만 존재하고 바디가 선언되어있지 않음 -> 추상메서드
}

📍추상 클래스는 미완성 설계도이기 때문에 메서드 바디가 완성되기 전까지 객체 생성 불가

AbstractExample abstractExample = new AbstractExample(); // 에러발생.
  • 추상 클래스를 사용하면 상속을 받는 하위 클래스에서 오버라이딩을 통해 각각 상황에 맞는 메서드 구현이 가능해짐
  • 상속계층도 상층부에 위치할수록 추상화의 정도가 높고, 그 아래로 내려갈수록 구체화됨

 

🔎 fianl 키워드

➡️ 최종의/마지막의 뜻을 가짐, 변경이 불가능하고 확장할 수 없음

➡️ 필드, 지역변수, 클래스 앞에 위치 가능하며 위치에 따라 의미가 달라짐 

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

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

 

 

🔎 인터페이스(Interface)

➡️ 서로 다른 두 시스템, 장치, 소프트웨어 따위를 서로 이어주는 부분 또는 그런 접속 장치

➡️ 추상화를 구현한다는 점에서는 추상 클래스와 비슷하지만 그에 비해 더 높은 추상성을 가짐

  • 추상 클래스 : 바디가 없는 추상 메서드를 하나 이상 포함
  • 인터페이스 : 기본적으로 추상 메서드와 상수만을 멤버로 가짐 → 추상 메서드의 집합

 

✍🏻 인터페이스의 기본 구조

➡️ 기본적인 클래스를 작성하는 것과 유사하지만 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 생략 
}

// 생략된 부분은 컴파일러가 자동 추가
// 추상메서드와 상수만으로 구성

 

 

✍🏻 인터페이스의 구현 

➡️ 인터페이스 그 자체로 인스턴스를 생성할 수 없고, 메서드 바디를 정의하는 클래스를 따로 작성해야 함

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

// 특정 인터페이스를 구현한 클래스는 해당 인터페이스에 정의된 모든 추상 메서드를 구현해야 함 
// 어떤 클래스가 특정 인터페이스를 구현한다는 것은 그 클래스에게 인터페이스의 추상 메서드를 반드시 구현하도록 강제하는 것 
// 즉, 그 인터페이스가 가진 추상 메서드를 해당 클래스 내에서 오버라이딩한다는 것

 

 

✍🏻 인터페이스의 다중 구현

➡️ 클래스 간의 다중 상속은 허용되지 않으나 인터페이스는 다중적 구현 가능
    → 하나의 클래스가 여러 개의 인터페이스를 구현할 수 있음 

➡️ 인터페이스는 인터페이스로만 상속 가능, 클래스와 달리 Object와 같은 최고 조상 존재하지 않음

➡️ 인터페이스는 애초에 미완성된 멤버를 가지고 있기 떄문에 충돌이 발생할 여지 없고 안전하게 다중 구현 가능 

⭐️ 특정 클래스는 다른 클래스로부터의 상속을 받으면서 동시에 인터페이스를 구현할 수 있음

 


용어의 늪에 빠졌음... 머릿속으로는 이해가 됐다 싶으면서도 막상 코드로 살펴보면 적용이 바로바로 되지 않는다. 몇 번이고 분석만이 살 길임을 새삼 깨달았다. 객체 지향의 핵심 원리 네 가지는 몇 번이고 정리한 것을 다시 살펴봐야겠다. 튼튼한 기초가 준비되지 않으면 결국에는 가다가 흔들리기 마련이다. 오늘도 마지막 세션 때 같이 코드를 짜는 시간에 자꾸 얘가 어디서 왔더라? 어떻게 호출됐지? 하면서 굉장히 헷갈렸다. 다시 어제처럼 코드의 흐름을 천천히 따라가 봐야겠다.

BELATED ARTICLES

more