-
객체지향프로그래밍(OOP) 개념의 기초적인 이해각종 학습 요약/Java 2022. 5. 10. 12:05
객체 지향 프로그래밍(OOP, Object-Oriented Programming) 개념의 기초
기본 구성
클래스(Class): 같은 분류로 묶이는(같은 기능/목적을 가지는) 속성들(멤버변수로 표현된다)과 행위들(메소드로 표현된다)의 정의. OOP에서는 클래스를 사용자가 정의한 데이터 타입으로써 사용한다(참조타입).
Java에서는 다음과 같은 식으로 정의된다.class Car { // 멤버(혹은 필드) (속성) private String name = "MustangGT"; // 메소드 (행동) public void startUp(Key key) { ... } // 생성자 public Car() { ... } public Car(Driver driver) { ... } class CarInner { ... } /* 클래스 내부에 일회성의 '이너클래스'가 존재할 수 있다. */ }
인스턴스(Instance): 클래스를 메모리 상에 로드하여 런타임 상 고유의 속성과 행위를 갖게된 상태. 쉽게 말해, 개념적인 대상이 실재하게 된 상태를 말한다. Java에서는 new 연산자를 이용한 생성자 호출을 통해 인스턴스화 한다.
...(생략)... Driver.name = "Nick"; Car myCar = new Car(driver); ...(생략)...
객체(Object): 개념적으로는 분류와 표현이 가능한 모든 것을 객체라고 한다.
OOP 안에서의 객체는 인스턴스와 클래스를 포함한 개념이지만, Java 안에서의 객체는 본래 인스턴스(추상 자료형(Class)의 인스턴스)를 말하는 것이고, 클래스는 객체의 타입 정도로 보는 듯하다.
또한 한 객체에서 다른 객체의 메서드를 이용해서 호출하는 행위를 '메시지를 보낸다'라고 한다.
특징
각 특징에 들어가기 앞서: 객체지향의 모든 특징은 '객체는 단일하지 않고, 서로 소통한다'는 것이다. '인간'이라는 것의 특징이 하나의 개체일 때는 단지 조금 특별한 동물 정도지만, 여러 개체 간의 커뮤니케이션을 통해 인간 사회의 독특함이 드러나는 것으로 비유하고 싶다. 모든 객체는 커뮤니케이션 한다.
나는 아래의 특징들을 이해하기를, 적절한 커뮤니케이션 방법과 객체 관계 간의 특징 정도로 이해하고 있다.추상화: 커뮤니케이션에 필요한 정보만 노출하고, 나머지는 감추는 것. 편의점에서 상품을 거래하면서 주민번호를 노출한다든가 나의 성장배경을 노출하지는 않는다. 현재 행동의 목적(편의점 상품 거래)과 상관이 없어서 굳이 밝힐 필요가 없는 내용이며, 다른 속성에 영향을 끼칠 수 있는 민감한(감춰야할) 정보기 때문이다.
Java에서는 접근제어를 통한 캡슐화와도 연관이 있다.상속: 새로운 클래스가 기존 클래스의 속성과 행동을 물려받도록 하는 기능. 새로운 클래스('자식 클래스'라고 한다)가 기존 클래스('부모 클래스'라고 한다)에 종속되는 관계가 형성되며, 기존의 클래스에 속성과 행동을 덧붙여 확장할 수 있다.
- 다중상속: 말 그대로 여러 클래스를 부모로 삼는 것이다. 하지만 종속관계가 혼동될 수 있다는 단점이 존재한다. Java에서는 존재하지 않는 개념이고, C#에서는 지원한다.
다형성: 이건 예부터 들어보려고 한다.
(대상 물체를) 들어줘!
만약 내가 옆사람에게 위와 같은 말을 하고 싶은 상황이라고 하자. 하지만 그 물체가 무엇이냐에 따라 매우 다른 상황이 펼쳐질 수도 있다.
떨어뜨린 핸드폰을 "들어줘!"라고 말하면 "손가락을 펼쳐서 가볍게 집듯이 핸드폰을 주워줘!"라는 의미가 될 것이고, 앞에 쓰러진 사람을 보고 병원에 전화하면서 옆을 지나던 소방구급대원 분께 "들어줘!"라고 말하면 "환자가 다치지 않도록 상체를 조심스레 들어서 등에 들쳐업어줘!"라는 의미가 될 것이다. 이 행동들은 모두 "들어줘!"란 말로 공통되게 표현할 수 있다.
하지만 만약 어떤 사람(들어줄 사람)이 "들어줘!"란 말을 들었을 때, "응? 뭘 어떻게 들으란거지? 내가 들을 대상은 뭔데? 어떤 식으로 들어줬으면 좋겠어?"라고 말한다면, 난 그 사람과 대화하는 것이 조금 피곤하게 될 것 같다. 특별히 구체화 될 필요가 있지 않은 이상, "들어줘!"라는 말을 전달했을 때, 적당히 알아서 잘 "들어주면" 가장 좋은 것이다.OOP의 이야기로 돌아오면, 클래스의 각 행동들은 필연적으로 어떤 요소를 사용하고 조작한다. 그 행동들을 구분할 때, 값이 아닌 행동을 기준으로 구분하는 성질을 다형성이라고 한다.
다루는 값을 기준으로 행동을 구분하는 것과 행동을 기준으로 행동을 구분하는 것의 예를 하나씩 들어보자.
만약 숫자(int)를 스트링 타입으로 변환하는 행동과 날짜를 스트링 타입으로 변환하는 행동을 각각 정의하고 싶다.
값을 기준으로 행동을 정의해야 한다면 코드는 대략 이런 식이 될 것이다.String str1 = IntToString(intValue); String str2 = DateToString(dateValue);
하지만 이 코드에서는 불필요함을 느낄 수 있다. 두 행동 모두 '스트링으로 변환한다'는 행동인데, 다루는 값의 타입때문에 마치 각각 다른 행동처럼 둘로 구분되는 것이다.
그래서 다형성 개념을 적용해서, 행동을 정의할 때에 행동을 기준으로 코드를 만들면 이렇게 될 것이다.String str1 = intValue.toString(); String str2 = dateValue.toString(); // 또는 String str1 = String.valueOf(intValue); String str2 = String.valueOf(dateValue);
이렇듯 '입력값을 스트링 값으로 변환한다(
toString() 또는 valueOf()
)'라는 '행동'을 기준으로 행동을 적용하니 자연스러워진 것을 볼 수 있다.
참고로 위의 방식은 오버라이딩을 통한 다형성 개념의 적용이고 아래는 오버로딩을 통한 다형성 개념의 적용인데, 이건 다음 포스팅에서 알아보자.- 동적 바인딩 : 개념적인 설명만으로는 크게 와닿지 않을 개념이지만 매우 중요하기도 하다. Java에서는 동적/정적 바인딩을 모두 사용하지만, 동적 바인딩을 통해서 다른 특징들이 가능한 점도 있기 때문이다. 그래서 짧게만 설명하고, 나중에 실습 예시와 함께 풀어보고 싶다.
짧게 말하자면, 런타임(실행 시간)에 추상타입의 구체 클래스가 결정되는 것이라 말할 수 있을 것 같다.
개인적으로는, 뭔 소린지 전혀 이해가 가지 않아도 상관 없을 것 같다.
장점
읽어보면 알겠지만, 각 특징들이 딱 구분되는 별개의 것이 아니라 상호 연관이 있으므로 서로 어떤 연관이 있을지도 생각해보자.
위에 설명한 특징들로 인해 객체지향의 장점들이 나타나는데, 각각의 장점들이 어떤 내용인지까지 설명하려면 기초를 넘어갈 것 같으니 대강 이름을 가지고 있는지 훑어만 보자(실은, 궁금하면 키워드로 직접 찾아보라는 말이다...) : 강한 응집력(Strong Cohesion), 약한 결합력(weak coupling) 등...'각종 학습 요약 > Java' 카테고리의 다른 글
Java: 제네릭 Generic (4) 2022.05.17 추상클래스와 인터페이스의 차이와 선택 기준 (0) 2022.05.13 # Java의 상속 개념 : inheritance, composite (2) 2022.05.12 Java: 생성자(Constructor)의 기본적인 이해 (0) 2022.05.11 클래스와 인스턴스의 관계 이해하기 (0) 2022.05.10 조금 특별한 타입: String (0) 2022.05.06