---
description: 자바 객체 지향
---

# Week 1(2/2) - OOP

<details>

<summary>오버로딩과 오버라이딩의 차이는 뭔가요?</summary>

**오버로딩**은 같은 이름의 메서드를 여러 개 정의하는 것이며, 주로 메서드의 매개변수 목록(파라미터 리스트)을 다르게 설정하여 구현됩니다.

**오버라이딩**은 상속 관계에 있는 클래스에서 부모 클래스의 메서드를 재정의하는 것을 의미합니다.

</details>

<details>

<summary>다형성이 무엇이고, 왜 필요할까요?</summary>

같은 메서드나 연산자가 서로 다른 클래스에서 다양한 방식으로 동작할 수 있게 하는 능력을 의미합니다. 쉽게 말해, "하나의 인터페이스에 대해 여러 가지 형태의 구현이 가능하다"는 것을 뜻합니다.

* 컴파일타임 다형성 (Compile-time Polymorphism) / 정적 다형성 (Static Polymorphism). 주로 **메서드 오버로딩**을 통해 구현됩니다.
* 런타임 다형성 (Runtime Polymorphism) / 동적 다형성 (Dynamic Polymorphism). 주로 **메서드 오버라이딩**과 **인터페이스**를 통해 구현됩니다.



* 유연성과 확장성\
  다형성은 코드의 유연성을 크게 높여줍니다. 예를 들어, 여러 종류의 객체가 동일한 인터페이스를 구현하거나 같은 부모 클래스를 상속받아 메서드를 오버라이딩하면, 특정 객체의 타입에 의존하지 않고 동일한 방식으로 메서드를 호출할 수 있습니다. 이를 통해 새로운 클래스나 기능을 추가할 때 기존 코드를 수정하지 않고도 확장할 수 있습니다.

- **코드 재사용성**:\
  다형성을 활용하면 공통된 인터페이스나 부모 클래스를 통해 코드의 재사용성을 높일 수 있습니다. 여러 클래스에서 동일한 메서드 시그니처를 사용하여, 다양한 객체가 동일한 방식으로 처리되도록 코드를 작성할 수 있습니다.

* 유지보수의 용이성\
  다형성은 유지보수를 쉽게 해줍니다. 예를 들어, 새로운 타입이 추가되거나 기존 타입이 변경될 때, 공통 인터페이스나 부모 클래스의 메서드만 수정하면 됩니다. 이를 통해 코드의 수정 범위를 최소화할 수 있습니다.

</details>

<details>

<summary>상속은 무엇인가요?</summary>

기존의 클래스를 재사용하여 새로운 클래스를 만드는 방법입니다. 상속을 통해 새로운 클래스(자식 클래스 또는 서브클래스)는 기존 클래스(부모 클래스 또는 슈퍼클래스)의 필드(멤버 변수)와 메서드(멤버 함수)를 물려받을 수 있습니다. 상속을 통해 코드의 재사용성과 확장성을 높일 수 있으며, 상위 클래스에서 정의한 기능을 하위 클래스에서 재사용하거나 확장할 수 있습니다.

</details>

<details>

<summary>상속의 단점은 무엇이 있을까요?</summary>

* 부모 클래스와 자식 클래스 간의 강한 결합
* 설계의 복잡성 증가

</details>

<details>

<summary>상속과 조합의 차이에 대해 설명해 주세요.</summary>

상속은 부모 클래스(슈퍼클래스)의 속성과 동작(메서드)을 자식 클래스(서브클래스)에 물려주는 메커니즘입니다. 상속을 통해 자식 클래스는 부모 클래스의 모든 멤버(필드와 메서드)를 상속받아 사용할 수 있으며, 필요에 따라 부모 클래스의 메서드를 오버라이딩(Overriding)하여 새로운 동작을 정의할 수도 있습니다.

조합은 객체가 다른 객체를 자신의 멤버 변수로 포함하여 기능을 재사용하는 방식입니다. 조합을 사용하면 객체는 포함된 다른 객체의 기능을 사용하면서도 각 객체가 독립적으로 존재할 수 있습니다. 조합은 일반적으로 **"has-a"** 관계를 나타냅니다.



상속과 조합의 차이점

* **관계**:
  * **상속**: **"is-a"** 관계를 나타냅니다. 자식 클래스는 부모 클래스의 일종이며, 부모 클래스의 특성을 상속받아 재사용합니다.
  * **조합**: **"has-a"** 관계를 나타냅니다. 객체는 다른 객체를 포함하고 있으며, 이 포함된 객체의 기능을 사용합니다.
* **재사용성**:
  * **상속**: 부모 클래스의 모든 멤버(필드와 메서드)를 자식 클래스가 상속받습니다. 이는 코드 재사용에 유리하지만, 부모 클래스에 의존적입니다.
  * **조합**: 다른 객체를 포함하여 그 객체의 기능을 사용할 수 있습니다. 각 객체는 독립적으로 존재하며, 유연성이 높습니다.
* **결합도**:
  * **상속**: 부모 클래스와 자식 클래스 간의 강한 결합(의존성)이 존재합니다. 부모 클래스의 변경이 자식 클래스에 영향을 미칠 수 있습니다.
  * **조합**: 결합도가 낮고, 포함된 객체는 독립적으로 변경될 수 있습니다. 이는 유지보수와 확장성 측면에서 유리합니다.
* **확장성**:
  * **상속**: 계층 구조가 깊어지면 클래스 간의 관계가 복잡해지고, 유지보수가 어려워질 수 있습니다.
  * **조합**: 필요에 따라 객체 간의 관계를 쉽게 변경하거나 확장할 수 있습니다. 새로운 기능을 추가하기 위해 상속보다는 조합이 더 유연한 방법이 될 수 있습니다.

</details>

<details>

<summary>instanceof 키워드란 무엇인가요?</summary>

`instanceof`는 Java에서 사용되는 키워드로, 객체가 특정 클래스나 인터페이스의 인스턴스인지 여부를 검사하는 데 사용됩니다. 이 키워드는 주로 객체의 타입을 확인하거나, 안전하게 타입 캐스팅을 하기 전에 타입을 검증할 때 사용됩니다.

</details>

<details>

<summary>instanceof 키워드를 사용할 때 문제점으로 무엇이 있을까요?</summary>

* 타입 종속성 증가
* 다형성의 저해
* 복잡한 논리와 가독성 저하

</details>

<details>

<summary>interface란 무엇일까요?</summary>

Java에서 클래스나 객체가 특정 기능을 수행하기 위해 반드시 구현해야 하는 메서드들의 집합을 정의한 것입니다. 인터페이스는 객체 지향 프로그래밍에서 다형성을 구현하는 중요한 도구로, 클래스가 어떤 동작을 수행할 수 있는지를 명시하지만, 그 동작의 구체적인 구현은 클래스에 맡깁니다.

</details>

<details>

<summary>interface와 abstract class는 어떤 차이가 있나요?</summary>

#### **다중 상속 지원 여부**

* **인터페이스**: Java에서는 클래스가 여러 인터페이스를 \*\*구현(implements)\*\*할 수 있습니다. 이를 통해 다중 상속을 우회적으로 지원하며, 다양한 기능을 한 클래스에 포함시킬 수 있습니다.
* **추상 클래스**: 클래스는 하나의 추상 클래스만 \*\*상속(extends)\*\*할 수 있습니다. 다중 상속은 허용되지 않으며, 이는 클래스 간의 관계를 단순화하고, 다중 상속으로 인한 모호성을 방지하기 위함입니다.

#### 2. **메서드 구현 여부**

* **인터페이스**: Java 8 이전의 인터페이스는 메서드의 시그니처만 선언할 수 있고, 메서드의 구현을 포함할 수 없었습니다. Java 8 이후로는 **디폴트 메서드**(default methods)와 **정적 메서드**(static methods)를 인터페이스에 포함할 수 있으며, 이들은 기본적인 구현을 가질 수 있습니다. 그러나 인터페이스의 메서드 구현은 제한적이며, 주요 목적은 구현을 강제하는 것입니다.
* **추상 클래스**: 추상 클래스는 추상 메서드뿐만 아니라, **일반 메서드**(구현된 메서드)도 가질 수 있습니다. 이는 공통된 기능을 여러 서브클래스에서 공유하면서도, 특정 기능은 서브클래스에서 구현하도록 강제할 수 있습니다.

#### 3. **필드(변수) 사용**

* **인터페이스**: 인터페이스 내에서는 **상수**(public static final)만 선언할 수 있으며, 인스턴스 변수를 가질 수 없습니다. 모든 필드는 자동으로 `public static final`로 간주됩니다.
* **추상 클래스**: 추상 클래스는 인스턴스 변수(필드)를 가질 수 있습니다. 이를 통해 상태를 유지하거나 서브클래스에서 공유할 공통된 데이터를 정의할 수 있습니다.

#### 4. **생성자**

* **인터페이스**: 인터페이스에는 생성자가 없습니다. 인터페이스는 인스턴스화할 수 없으며, 인터페이스 자체로 객체를 만들 수 없습니다.
* **추상 클래스**: 추상 클래스는 생성자를 가질 수 있으며, 서브클래스에서 추상 클래스를 상속받을 때 해당 생성자를 호출할 수 있습니다. 추상 클래스는 인스턴스를 만들 수 없지만, 생성자는 서브클래스 초기화 시 사용할 수 있습니다.

#### 5. **사용 목적**

* **인터페이스**: 인터페이스는 주로 **기능**을 정의하는 데 사용됩니다. 클래스가 어떤 동작을 수행해야 하는지 명시하는 역할을 하며, 다양한 클래스에서 동일한 동작을 구현하도록 강제합니다. 인터페이스를 구현한 클래스들은 각기 다른 상속 계층에 속할 수 있으며, 특정 기능을 공통적으로 구현하게 됩니다.
* **추상 클래스**: 추상 클래스는 **상속받는 클래스들 간의 공통된 특성**을 정의하는 데 사용됩니다. 서브클래스 간의 공통된 속성이나 동작을 공유하고, 일부 동작만을 서브클래스에서 정의하도록 강제합니다.

#### 6. **추상화 수준**

* **인터페이스**: 인터페이스는 100% 추상화를 제공합니다. 모든 메서드는 기본적으로 추상적이며, 객체가 수행해야 하는 동작을 정의합니다.
* **추상 클래스**: 추상 클래스는 부분적인 추상화를 제공합니다. 일부 메서드는 구현이 되어 있을 수 있고, 일부 메서드는 서브클래스에서 구현하도록 강제할 수 있습니다.

</details>

<details>

<summary>언제 interface 사용하고, 언제 abstract class 사용 하나요?</summary>

#### **인터페이스(interface)를 사용할 때**

1.  **다중 상속이 필요할 때**:

    Java에서는 클래스가 하나의 클래스만 상속받을 수 있지만, 여러 개의 인터페이스를 구현할 수 있습니다. 따라서 클래스가 여러 개의 기능을 가져야 하며, 이러한 기능들이 서로 관련이 없을 때 인터페이스를 사용합니다.

2) **행동을 명시할 때**:\
   인터페이스는 특정 클래스가 어떤 행동을 수행할 수 있는지를 정의합니다. 예를 들어, 여러 클래스가 공통적으로 수행해야 하는 행동이 있지만, 이 행동이 클래스의 계층 구조와 관련이 없을 때 인터페이스를 사용합니다.
3) 클래스 간의 관련성이 없을 때\
   서로 관련이 없는 여러 클래스에 공통적인 행동을 정의하고 싶을 때 인터페이스를 사용합니다.
4) 상수 필드가 아닌 필드를 포함하지 않을 때

**추상 클래스(abstract class)를 사용할 때**

1. 클래스 간에 공통된 코드가 있을 때
2. 기본 구현을 제공할 때\
   추상 클래스는 일부 메서드에 대해 기본 구현을 제공할 수 있습니다. 이를 통해 자식 클래스는 필요한 메서드만 오버라이딩하고, 나머지는 기본 구현을 사용할 수 있습니다.
3. 상태(필드)를 가지는 공통 클래스를 만들고자 할 때\
   추상 클래스는 필드를 가질 수 있으므로, 자식 클래스 간에 공유될 공통 상태를 유지할 수 있습니다. 인터페이스는 상태를 가질 수 없으므로, 상태를 유지해야 한다면 추상 클래스를 사용해야 합니다.
4. 상속 계층 구조에 속한 클래스를 만들고자 할 때\
   추상 클래스는 계층 구조를 통해 클래스 간의 상속 관계를 명확히 할 수 있습니다. 만약 클래스들이 서로 밀접하게 관련되어 있고, 공통된 특성을 물려받아야 한다면 추상 클래스를 사용합니다.

</details>

<details>

<summary>final 키워드에 대해 설명해 주세요.</summary>

`final` 키워드는 Java에서 변수, 메서드, 클래스에 사용할 수 있는 키워드로, 변경할 수 없는 상태를 명시적으로 표현하는 데 사용됩니다.

* 변수에 사용: 변수는 초기화된 후 값을 변경할 수 없습니다.
* 메서드에 사용: 오버라이딩 불가
* 클래스에 사용: 클래스는 다른 클래스가 상속할 수 없습니다

</details>
