-
Notifications
You must be signed in to change notification settings - Fork 3
[재현] 익명클래스 #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
[재현] 익명클래스 #2
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
208 changes: 208 additions & 0 deletions
[CS_01] 기본지식/익명클래스.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
# 익명클래스, 추상클래스, 인터페이스 | ||
|
||
Created by: 이재현 | ||
Created time: 2023년 7월 6일 오후 9:54 | ||
Tags: JAVA | ||
|
||
## 익명 클래스란? | ||
|
||
- 말그대로 클래스의 이름을 정하지 않는 것으로, | ||
한번만 사용되고 버리고자 한다면 사용할 수 있다. | ||
- 일반적으로 어떤 클래스의 자원을 상속받아 재정의하여 사용하기 위해서는 | ||
자식이 될 클래스를 만들고 상속받아서 객체 인스턴스 초기화를 해야 한다. | ||
|
||
```java | ||
package week1; | ||
|
||
class Animal { | ||
public void func() { | ||
System.out.println("Animal! Animal!"); | ||
} | ||
} | ||
|
||
class Cat extends Animal { | ||
@Override | ||
public void func() { | ||
System.out.println("Meow! Meow!"); | ||
} | ||
} | ||
|
||
public class ex1 { | ||
public static void main(String[] args) { | ||
Animal a = new Cat(); | ||
a.func(); | ||
} | ||
} | ||
``` | ||
|
||
 | ||
|
||
- 위 예제 코드를 익명 클래스로 바꾸어보자. | ||
- 따로 클래스를 정의하지 않고도 메소드 내에서 바로 클래스를 생성하여 인스턴스화를 할 수 있으며, 이로부터 클래스의 선언 및 객체의 생성을 동시에 수행하므로 단 한 번만 사용된다. | ||
- 익명으로 정의된 클래스는 일회용으로 사용되고 버려진다. | ||
- 그러므로 단 한번만 정의하고 사용하고자 하는 클래스는 익명 클래스로 선언하는 것이 메모리 관점에서 효율적일 수 있다. | ||
- 생성된 익명 객체는 다른 객체와 마찬가지로, 더이상 사용되지 않는다고 판단되면 GC 에 의해 회수된다. | ||
|
||
```java | ||
package week1; | ||
|
||
class Animal { | ||
public void func() { | ||
System.out.println("Animal! Animal!"); | ||
} | ||
} | ||
|
||
public class ex1 { | ||
public static void main(String[] args) { | ||
Animal a = new Animal(){ | ||
@Override | ||
public void func(){ | ||
System.out.println("Meow! Meow!"); | ||
} | ||
}; | ||
a.func(); | ||
} | ||
} | ||
``` | ||
|
||
 | ||
|
||
<aside> | ||
💡 **재사용하지 않을 클래스를 익명 클래스로 선언하면 코드를 보다 간편하게 줄일 수 있고, 메모리 관점에서 효율적이라고 할 수 있다.** | ||
|
||
</aside> | ||
|
||
### 일반적으로 인터페이스를 구현할 때 익명 클래스를 자주 사용한다. | ||
|
||
- 아래의 예시를 보자. | ||
|
||
`Calculator` 클래스의 `int result(Operate op)` 메서드는 전달받는 `Operate` 객체의 `act` 메서드에 의해서 반환값이 달라진다. | ||
|
||
```java | ||
public class Calculator { | ||
int a; | ||
int b; | ||
public Calculator(int a, int b) { | ||
this.a = a; | ||
this.b = b; | ||
} | ||
public int result(Operate op){ | ||
return op.act(a, b); | ||
} | ||
} | ||
``` | ||
|
||
- `Operate` 는 아래와 같이 `int act(int a, int b)` 를 멤버로 가지는 인터페이스로 구현되어 있다. | ||
|
||
```java | ||
public interface Operate { | ||
int act(int a, int b); | ||
} | ||
``` | ||
|
||
- 따라서 Calculator 가 덧셈기로 동작하도록 하려면, | ||
Operate 를 구현한 Plus 라는 객체를 만들어서 사용해야 한다. | ||
|
||
```java | ||
public class Plus implements Operate { | ||
@Override | ||
public int act(int a, int b) { | ||
return a + b; | ||
} | ||
} | ||
``` | ||
|
||
```java | ||
public class ex2 { | ||
public static void main(String[] args) { | ||
Calculator calc = new Calculator(20, 10); | ||
Operate op = new Plus(); | ||
System.out.println(calc.result(op)); | ||
} | ||
} | ||
``` | ||
|
||
 | ||
|
||
- 하지만 이렇게 구현하면 문제가 다소 발생한다. | ||
- 뺄셈 기능을 사용하려면 Minus 라는 객체를 만들어야하고... | ||
- 나눗셈 기능을 사용하려면 Divide 라는 객체를 만들어야할테고... 🫠 | ||
- 이러한 상황에서 익명 클래스를 사용하면 매우 효율적이다. | ||
|
||
```java | ||
public class ex2 { | ||
public static void main(String[] args) { | ||
Calculator calc = new Calculator(20, 10); | ||
int result = calc.result(new Operate() { | ||
@Override | ||
public int act(int a, int b) { | ||
return a - b; | ||
} | ||
}); | ||
System.out.println(result); | ||
} | ||
} | ||
``` | ||
|
||
 | ||
|
||
- 람다식을 이용하면 보다 간결하게 작성할 수 있다. | ||
|
||
```java | ||
public class ex2 { | ||
public static void main(String[] args) { | ||
Calculator calc = new Calculator(20, 10); | ||
int result = calc.result((a, b) -> a - b); | ||
System.out.println(result); | ||
} | ||
} | ||
``` | ||
|
||
--- | ||
|
||
## 추상 클래스와 인터페이스의 개념과 공통점 | ||
|
||
(추상 클래스와 인터페이스의 차이점에 관한 질문이 면접에서 자주 등장한다고 한다.) | ||
|
||
- **모 블로그의 면접 후기 🥲🥲** | ||
|
||
 | ||
|
||
- 추상 메서드란 내부가 구현되지 않은 메소드이다. | ||
|
||
```java | ||
public interface Animal{ | ||
public void sound(); // 추상 메서드 | ||
} | ||
``` | ||
|
||
- 추상 클래스는 추상 메서드를 포함하고 있는 클래스를 의미한다. | ||
- 인터페이스는 모든 메서드가 추상 메서드로만 이루어진 클래스이다. | ||
- 추상 클래스와 인터페이스는 하위 클래스에서 구현을 강제하는 추상 메서드를 포함한다는 공통점이 있다..! | ||
- 근데 굳이 왜 두 개가 나뉜걸까..?? | ||
|
||
--- | ||
|
||
## 추상 클래스와 인터페이스의 차이점 | ||
|
||
- 핵심 키워드는 `상속` ********************이다. | ||
- 우선 자바에서는 클래스의 다중 상속을 지원하지 않는다. | ||
- 아래와 같은 `다이아몬드 상속` 문제를 방지하기 위해 지원하지 않도록 결정했다고 한다. | ||
|
||
 | ||
|
||
- `ComboDrive` 클래스에서 구현해야 할 `burn()` 은 누구로부터 온것인가?! 🫠 | ||
- 위와 같이 상위 클래스에서 같은 이름의 메서드가 존재한다면, 하위 클래스에서 그 메서드를 호출했을 때 실제로 어떤 메서드가 호출되어야 할 지 모호해진다. | ||
- 하지만 인터페이스는 다른 클래스와는 다르게 **다중 상속**이 가능하다! | ||
- 애초에 모든 메서드가 추상 메서드로 이루어져있기 때문에 다이아몬드 문제는 우려하지 않아도 된다. | ||
- 다중 상속 받은 하위 클래스는 상속받은 모든 인터페이스를 구현해야 하고, 모든 상위 인터페이스의 구현체로 사용할 수 있다. | ||
- 하지만 다중상속만이 인터페이스의 존재 이유라고 이야기 할 수는 없다. | ||
- 인터페이스를 상속받은 클래스는 모든 추상 메서드를 재정의하여야 하므로, 하위 클래스에게 일종의 설계도와 같은 역할을 수행한다. | ||
- 추상클래스는 조금 다르다. 하위 클래스는 상속받은 추상 클래스의 기존 메서드는 그대로 이용하고, 추상 메서드만 확장하는 역할을 수행한다. | ||
|
||
<aside> | ||
💡 **즉, 추상 클래스는 상속 받은 클래스의 기능을 이용하고 확장하는 것이 주목적이고 인터페이스는 하위 클래스에게 일종의 설계도와 같은 역할을 제공한다는 것이 중요하다!** | ||
|
||
</aside> | ||
|
||
--- |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.