[JAVA] ch6: 객체지향설계(OOD)

oow·2026년 4월 18일

JAVA

목록 보기
11/13

객체지향설계

상속성

상속은 기존 클래스의 속성과 메소드를 자식 클래스가 물려받아 사용하는 것을 말한다. 코드를 재사용, 확장하여 사용할 수 있어 객체지향의 핵심 개념이다. 단, 속성이나 메소드가 같다고 해서 상속을 남발하지 않는다. "Is-A" 논리 관계일 경우에만 사용한다. 예를 들어, s26 extends s25라면 s26 is-Kind-of s25 관계여야 한다. 부모를 만든 후 자식을 만드는 top-down 방식이다.

부모가 허용한 속성과 메소드만 사용 가능하며, 생성자는 물려주지 않는다. 자식 클래스는 새로운 고유 속성과 메소드를 추가하는 것도 가능하지만, 부모가 물려준 메소드를 재정의하는 오버라이딩도 가능하다.

일반화는 상속과 유사한 개념으로, 클래스들의 공통 속성이나 기능이 있을 때 상위 클래스를 만들어 일반화하는 것이다. 각 클래스의 고유한 속성이나 기능은 하위 클래스에 정의한다. -> 계층 구조이다. 자식들을 모아 부모를 만드는 bottom-up 방식이다.

  • 일반화(is-Kind-of)가 가능해야 상속할 수 있다.



클래스의 계층 구조

상속은 상위 클래스이ㅡ 멤버를 하위 클래스가 물려받는 것이다. extends를 사용한다. 앞서 서술했듯 "Is-A" 관계여야 한다. 수직으로 다계층 구조가 가능하여 하위 클래스로 갈수록 개념이 구체화, 확장된다.

  • class 자식클래스 extends 부모클래스 {}

그러나 java에서는 다중 상속이 금지되어 있어 단 하나의 부모만 가질 수 있다. 다중 상속이 허용될 경우 구조가 복잡해지고 어느 부모에게서 메소드를 가져올지 모호해지기 때문이다. 단일 상속의 한계를 보완하기 위해 인터페이스를 활용한다.


구현은 하위 클래스의 역할, 기능, 능력을 정의하는 것으로, implements를 사용한다. "Can-Do" 논리 관계일 때 사용한다. 하위 클래스는 수평적으로 여러 개의 인터페이스를 가질 수 있다. 한 객체가 여러 능력을 가질 수 있다는 의미이다. 다중 구현이 허용되는 이유는 인터페이스는 기능을 정의할 뿐 구현은 자식 클래스에서 해야 하기 때문이다(모호성 x).

  • class 자식클래스 implements 기능1, 기능2 {}

또한 상속과 달리 "Is-A" 관계가 아니어도(같은 상속 트리가 아니어도) 능력이 같은 객체들을 하나로 묶을 수 있다.


Lab#6-1

  • Point 클래스를 상속받아 색상 속성을 추가한 ColorPoint 클래스를 만들 수 있다.
  • ColorPoint에서 Point 클래스의 속성과 메소드를 정의하지 않아도 사용할 수 있다.

Lab#6-2

  • 위와 같은 상속 관계에서 Human 객체를 생성할 경우 아래와 같이 Animal 객체를 생성한 후, Human 객체의 멤버를 덧붙인다.
  • 서브 클래스는 슈퍼 클래스의 멤버와 서브 클래스의 멤버를 모두 가진다.
  • 서브 클래스로 갈수록 구체화된다.

Lab#6-3, Lab#6-4

  • 기능과 관계에 따라 상속 관계를 정의할 수 있다.
    • Student는 Person이다. -> Student extends Person
    • StudentWorker는 Student이다. -> StudentWorker extends Student
  • Student, StudentWorker, Researcher, Professor의 중복된 멤버가 있다면, 상속을 이용하여 공통 기능을 부모 클래스로 작성 가능하다. -> 중복 제거
  • 다중 상속은 불가능하다.
  • 상속 깊이는 2~4단계가 적절하다. 상위 클래스는 모든 하위 클래스에 영향을 미치기 때문에 단계가 깊어지면 관계 파악이 어렵다. -> 위 UML처럼 파악이 쉬워야 한다.
  • StudentWorker 인스턴스를 생성한다면, Person을 만들고 -> Student를 붙이고 -> StudnetWorker를 붙이는 방식이다. => 상속&구체화

Lab#6-5

  • 인터페이스로 Student의 기능을 확장할 수 있다.
  • Study_able에서 정의한 기능은 Student에서 반드시 구현해야 한다(오버라이딩). -> 구현하지 않으면 오류 발생
  • 인터페이스에서는 기능 이름만 명시한다(추상화).
    • jdk 상위 버전에서는 인터페이스에서 구현이 가능하지만, 기본적으로는 불가능하다.
  • 인터페이스는 -able, I-와 같이 명명한다.



상속 관계에서의 접근 지정자

  • private 필드는 상속되지 않는다.
  • 상위 클래스의 protected 멤버는 다른 패키지의 클래스에서 접근 가능하다.
    • 다른 패키지에 있는 클래스를 사용할 경우 import로 패키지를 불러와야 한다.
  • default 멤버는 같은 패키지에서만 접근 가능하다.

Lab#6-6

  • 패키지 q의 클래스 B에서 패키지 p의 클래스 A를 상속받기 위해 import p.A 또는 import p.*가 필요하다.
  • B는 A와 다른 패키지이므로 def에 접근할 수 없다.
  • pri는 private이므로 하위 클래스에서 접근할 수 없다.
  • this.super.로 멤버에 접근한다. -> set()에서 this.을 입력하면 pro와 pub만 보인다.

Object 클래스

  • 모든 클래스는 자동으로 java.lang.Object를 상속받는다. -> extends 생략
  • 주요 메소드를 오버라이딩하여 사용한다. -> toString(), equals(), ...

다형성

다형성은 하나의 이름으로 여러 가지 형태를 구현하는 것이다. 메소드 오버라이딩과 오버로딩을 통해 구현한다. 동일한 이름의 호출에 어떤 객체가 응답하느냐에 따라 서로 다른 결과를 만들어낸다.

  • 메소드 오버라이딩은 상위 클래스의 메소드를 하위 클래스에서 재정의하는 것으로, 이름과 매개변수가 같아야 한다. 런타임에 결정되므로 동적 바인딩이다.
    • 런타임 시점에 어떤 메소드를 호출할지 결정한다는 의미이다. 하위 클래스에서 먼저 해당 메소드를 찾고, 없으면 상위 클래스로 올라가며 메소드를 찾는다.
    • 오류가 있어도 컴파일러를 통과할 수 있다.
    • @Override를 사용하면 오버라이딩에 오류가 있을 경우 컴파일러가 알려준다.
  • 메소드 오버로딩은 매개변수의 개수 또는 타입이 달라야 한다. 컴파일 시 결정되므로 정적 바인딩이다.

예를 들어, 부모 타입 배열을 생성하여 여러 자식 타입 객체를 담을 수 있다. 인터페이스 배열도 가능하다. -> 업캐스팅

  • 반복문으로 같은 메소드를 불러와도, 객체 타입에 따라 다른 결과가 실행된다.
  • 하위 클래스를 상위 클래스라고 부를 수 있다. -> 상위 클래스 배열에 하위 클래스 저장이 가능하다.
    • 반대는 불가능하다.

0개의 댓글