#5. ์๋ฐ์ Interface
by JiwonDev# Abstract Class (์ถ์ ํด๋์ค)
์ฐธ๊ณ ๋ก ํด๋์ค ๋ด๋ถ์ ๊ตฌํ๋ถ๊ฐ ์๊ณ , ์ ์ธ๋ง ๋์ด์๋ ๊ฒ์ Abstract Method(์ถ์ ๋ฉ์๋) ๋ผ๊ณ ํ๋ค. ์ถ์ ๋ฉ์๋๊ฐ ์กด์ฌํ๋ ํด๋์ค๋ abstract ํค์๋๋ฅผ ์ด์ฉํด ๋ฐ๋์ ์ถ์ ํด๋์ค๋ก ๋ง๋ค์ด์ผ ํ๋ค. ๊ฐ์ฒด์ ์ธ์คํด์ค๊ฐ ์์ฑ๋์ง ์๊ฒ ๋ฐฉ์งํ๊ธฐ ์ํจ์ด๋ค.
public abstract class Animal { public abstract String getFood(); }
์ฌ๋ฐ๋ ์ ์ ์ถ์๋ฉ์๋๊ฐ ํ๋๋ผ๋ ์์ผ๋ฉด ๋ฐ๋์ ํ์ํด์ฃผ์ด์ผ ํ์ง๋ง, ์ถ์๋ฉ์๋๊ฐ ์๋๋ผ๋ ๊ฐ์ฒด์ ์ธ์คํด์ค ์์ฑ์ ๋ฐฉ์งํ๊ธฐ ์ํด abstract class๋ฅผ ์ ์ธ ํ ์๋ ์๋ค. ์ด๋ Math ๊ฐ์ด ๊ตณ์ด ์ธ์คํด์ค๋ฅผ ๋ง๋ค ํ์๊ฐ ์๋ ํด๋์ค ๋ฑ์ ์ฌ์ฉ๋๋ค.
# Interface
์ธํฐํ์ด์ค๋ ์ถ์ ํด๋์ค์ ์ผ์ข ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค. ๋ค๋ง ์ด๋ฆ์์ ์ ์ถ ํ ์ ์๋ฏ์ด, ์ธํฐํ์ด์ค ๋ด๋ถ์๋ ์ถ์ ๋ฉ์๋(public abstract)์ ์์(static final)๋ง ์ฌ์ฉ ํ ์ ์๋ค.
interface MyInterface{ public static final int MY_VALUE = 10; int MT_VALUE2 = 10; // ์ธํฐํ์ด์ค์์๋ ์๋์ผ๋ก ์์ํ (static final) ๋๋ค. public abstract myMethod(); // ์ธํฐํ์ด์ค์์๋ abstract ํค์๋๋ฅผ ์๋ตํด๋ ์ ๋ถ public abstract๋ก ๊ฐ์ฃผํ๋ค. // ์๋ 3๊ฐ๋ ์ ๋ถ public abstract ์ด๋ค. public abstract myMethod1(); public myMethod2() ; myMethod3() ; }
# Default Method
๋ค๋ง ๊ธฐ์กด ์๋ฐ์์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํจ์ ์์ด, ์ฌ์ฉํ์ง ์๋ ์ถ์ ๋ฉ์๋๋ ์ ๋ถ ๊ตฌํํด์ฃผ์ด์ผ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๊ธฐ์ ๋ถํธํจ์ด ๋ง์๋ค. ๊ทธ๋์ Java8 ๋ถํฐ๋ default ํค์๋๋ฅผ ์ด์ฉํ์ฌ ๊ธฐ๋ณธ ๊ตฌํ ๊ฐ์ ์ ์ ์ ์๊ฒ ํด์ฃผ์๋ค.
package com.company; public interface Foo { void printName(); // ์ถ์๋ฉ์๋ 1 String getName(); // ์ถ์๋ฉ์๋ 2 // ์ด๋ฐ์์ผ๋ก default ํค์๋๋ฅผ ์ด์ฉํด ๊ธฐ๋ณธ๊ฐ์ ์ ์ ์ ์๋ค. default void printNameUpperCase(){ System.out.println(getName().toUpperCase()); } }
ํ์ง๋ง defalut ๋ฉ์๋๋ฅผ ๋๋ฌด ๋ฏฟ๊ณ ์ฌ์ฉํ๊ธฐ์๋ ์ฝ๋์ ์์ ์ฑ์ ๋ณด์ฅํ ์ ์๊ธฐ์ ์ธํฐํ์ด์ค์ JavaDoc์ ์ ์ฝ์ด๋ณด๊ณ ํ์ํ๋ค๋ฉด ๊ธฐ๋ณธ ๋ฉ์๋๋ฅผ @Overrideํด์ ์ฌ์ฉํ๋๋ก ํ์.
public interface Foo { /** * @implSpec * ์ด ๊ตฌํ์ฒด๋ getName()์ผ๋ก ๊ฐ์ ธ์จ ๋ฌธ์์ด์ ๋๋ฌธ์๋ก ๋ฐ๊ฟ ์ถ๋ ฅํ๋ค. */ default void printNameUpperCase(){ System.out.println(getName().toUpperCase()); } }
์ฐธ๊ณ ๋ก Object์์ ์ ๊ณตํ๋ ๋ฉ์๋ (equal, toString)๋ ์ธํฐํ์ด์ค์์ default๋ก ์ ์ ํ ์ ์๋ค. ์ฌ์ฉํ ๋ ค๋ฉด ๋ฐ๋์ ๊ตฌํ์ฒด๊ฐ ์ฌ์ ์ ๋์ด์ผ ํ๋ค.
public interface Foo { void printName(); // ์ถ์๋ฉ์๋ 1 String getName(); // ์ถ์๋ฉ์๋ 2 String toString(); // Object ๋ฉ์๋๋ ์ถ์๋ฉ์๋๋ก ์ ์๋ ๊ฐ๋ฅ. // default String toString(); // ์ปดํ์ผ ์๋ฌ!! default ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ๋ค. }
# ์ธํฐํ์ด์ค ์์
์ธํฐํ์ด์ค๋ ์์ํด์ ์ฌ์ฉ ํ ์ ์๋ค. ๋ถ๋ชจ์์ Default๋ก ๊ตฌํ ๋์ด์๋ ๋ถ๋ถ์ ์ถ์๋ฉ์๋๋ก ๋ณ๊ฒฝํ ์๋ ์๋ค.
์ฐธ๊ณ ๋ก ์๋ฐ์์๋ ์ฌ๋ฌ ๊ฐ์ฒด๋ค์ ๋์์ ์์ ํ ์ ์๊ธฐ์ ๋ค์ค์์ ์ค๋ณต ๋ฌธ์ (Diamond Problem)๊ฐ ์๊ธดํ๋ฐ, ์ด ๊ฒฝ์ฐ ์ปดํ์ผ ์๋ฌ๊ฐ ๋จ๋ ์ง์ ํ๋ํ๋ @Override ํด์ฃผ๋ฉด ๋๋ค. ๋ค๋ง ์ค์ ๊ฐ๋ฐ์์ ์ด๋ฐ์์ ๋ค์ค ์์์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๊ฑฐ์ ์๋ค.
public interface Foo { String getName(); default void printName();{ System.out.println("Hello"); } } public interface Bar extends Foo{ void printName(); // Foo ์ default๋ฉ์๋๋ฅผ ์์ ์ฃผ์๋ค. void newMethod(); }
# Java8์ ์ถ๊ฐ๋ ๊ธฐ๋ณธ ๋ฉ์๋, ์ธํฐํ์ด์ค
์์ ๊ฐ์ด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ฌ์ฉํ๊ธฐ ์ข๊ฒ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํด์ค์ผ๋ก์ ์ฌ๋ฐ๋ ๋ฉ์๋๋ค์ด ๋ง์ด ์ถ๊ฐ๋์๋ค. ์ด ๊ธ์์๋ ๊ฐ๋จํ๊ฒ ์ดํด๋ง ๋ณด๊ณ ๋ค์ ๊ธ์ ์์ธํ ์ค๋ช ํ๋๋ก ํ๊ฒ ๋ค.
Iterable์ ๊ธฐ๋ณธ ๋ฉ์๋
- forEach()
- spliterator()
import java.util.Arrays; import java.util.List; import java.util.Spliterator; public class Main { public static void main(String[] args) { List<String> name = Arrays.asList("Hi", "Bye", "Ho", "AB"); name.forEach(System.out::println); // ๊ฐ๊ฐ์ ์์๋ฅผ ์ถ๋ ฅ // split + iterator. ํฐ ๋ฐฐ์ด์ ๋ฐ์ผ๋ก ๋๋ ๊ฐ๊ฐ iter๋ฅผ ๋๋ฆด ์ ์๋ค. Spliterator<String> spliterator1 = name.spliterator(); Spliterator<String> spliterator2 = spliterator1.trySplit(); // ์๋์ผ๋ก ๋๋ ์ค๋ค. while(spliterator1.tryAdvance(System.out::println)); // "Hi", "Bye" while(spliterator2.tryAdvance(System.out::println)); // "Ho", "AB" } }
Collection์ ๊ธฐ๋ณธ ๋ฉ์๋
- stream() / parallelStream()
- removeIf(Predicate)
- spliterator()
public class Main { public static void main(String[] args) { List<String> name = Arrays.asList("KHi", "Bye", "KHo", "AB"); long nStartsWithK = name.stream().map(String::toUpperCase) .filter(str -> str.startsWith("K")) .count(); System.out.println(nStartsWithK); // 2 List<String> names = name.stream().map(String::toUpperCase) .filter(str -> str.startsWith("K")) .collect(Collectors.toList()); System.out.println(names); // ["KHi", "KHo"] } }
Comparator์ ๊ธฐ๋ณธ ๋ฉ์๋ ๋ฐ ์คํํฑ ๋ฉ์๋
- reversed()
- thenComparing()
- static reverseOrder() / naturalOrder()
- static nullsFirst() / nullsLast()
- static comparing()
+ Java9์ Private Method
์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค๋ฉด์ ์ฌ์ฉ์ ํธํ๊ฒ ํ๊ธฐ์ํด Java8์ default ๋ฉ์๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ์๋ค. ๊ทธ๋ฐ๋ฐ ์ฌ์ฉํ๋ค๋ณด๋ฉด default ๋ฉ์๋๊ฐ ๋จ์ํ ์ฌ์ฉ์ ํธํ๊ฒ ํ๊ธฐ์ํจ์ด ์๋๋ผ, ๊ณ ์ ๋ ๊ธฐ๋ณธ ๊ฐ์ ์ฃผ๊ณ ์ถ์ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ ๊ทธ๋ด ๋๋ฅผ ์ํด์ Java9๋ถํฐ private Method๋ผ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
Private ๋ฉ์๋๋ default ๋ฉ์๋์ ๋น์ทํ๋, ์ธํฐํ์ด์ค๋ฅผ ์์ ๋ฐ์์ ๋ด์ฉ์ ์์ ํ์ง ๋ชปํ๊ฒ ๋งํ์๋ค.
public interface Boo { /** * @implSpec ์ด ๋ฉ์๋๋ ์ค๋ฒ๋ผ์ด๋ ํ๊ฑฐ๋, ์ธ๋ถ์์ ์ ๊ทผํ ์ ์์ต๋๋ค. * @return "Bye" */ private String printBye(){ // default์ ๋์ผํ ๊ธฐ๋ฅ. ํ์ง๋ง ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅ return "Bye"; } default void knockDoor(){ System.out.println("Ok.. " + printBye()); } }
public class Main implements Boo{ @Override //Error -> method does not override or implement a method from a supertype public String printBye(){ return "Bye"; } }
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev