JiwonDev

#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

ํ™œ๋™ํ•˜๊ธฐ