๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Back-end ๋ฐ๋ธŒ์ฝ”์Šค/week 01 - 02 TIL (java, DB)

[TIL] 221019 - Java์˜ Interface

by young-ji 2022. 10. 19.

ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์œ„ํ•œ JAVA(3) - Java์˜ Interface

 

1.  Interface์˜ ๊ธฐ๋Šฅ

1๏ธโƒฃ ๊ตฌํ˜„์„ ๊ฐ•์ œ

 

2๏ธโƒฃ ๋‹คํ˜•์„ฑ ์ œ๊ณต

๋‹คํ˜•์„ฑ์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ

public class Main {
    public static void main(String[] args) {
        // ๋‹คํ˜•์„ฑ์ด ์—†์„๋•Œ - ๋กœ๊ทธ์ธ์„ ํ•˜๊ณ ์‹ถ๋‹ค. -> ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‘๊ฐœ ๋งŒ๋“ค๊ณ  ์กฐ๊ฑด์— ๋งž๊ฒŒ ํ˜ธ์ถœํ•ด์ค˜์•ผํ•œ๋‹ค.
        KakaoLogin KakaoUser = new KakaoLogin();
        NaverLogin NaverUser = new NaverLogin();

        KakaoUser.login();
        NaverUser.login();
    }
}

๋‹คํ˜•์„ฑ์„ ์ด์šฉํ•ด ๊ตฌํ˜„

public class Main {
    public static void main(String[] args) {
        // ๋‹คํ˜•์„ฑ์„ ์ด์šฉํ•œ ๊ตฌํ˜„
        // **ํ˜ธ์ŠคํŠธ ์ฝ”๋“œ** ์‹คํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋งŒ ๊ฒฐ์ •์„ ํ•œ๋‹ค -> ์„ค์ •ํŒŒ์ผ, config
        new Main().run(LoginType.Kakao)
    }

    // **๊ตฌํ˜„์ฝ”๋“œ์—์„œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ๊ฒฐ์ •ํ•˜์ง€ ์•Š์Œ** : ์ˆ˜์ •์—†์ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•จ
    void run(LoginType loginType){
        Login user = getLogin(loginType);
        user.login();
    }
    private static Login getLogin(LoginType type){
        if (type == LoginType.Kakao){
            return new  KakaoLogin();
        }else{
            return new NaverLogin();
        }
    }
}

 

3๏ธโƒฃ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋Š” ํšจ๊ณผ (์˜์กด์„ฑ ์—ญ์ „)

package com.programmers.java.poly;
public class UserService implements Login{
    private Login login; // ์บก์Šํ™”

    // ์˜์กด์„ฑ์„ ์™ธ๋ถ€์— ๋งก๊ฒจ ์˜์กด๋„๋ฅผ ๋‚ฎ์ถ˜๋‹ค. -> ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•  ์ž ์žฌ์„ฑ์„ ๊ฐ€์ง
    // ๊ตฌ์ƒ์ฒด์™€ ๊ฒฐํ•ฉํ•˜๋ฉด ๊ฒฐํ•ฉ์„ฑ ๊ฐ•ํ•ด์ง„๋‹ค. => ์ถ”์ƒ์ฒด์™€ ๊ฒฐํ•ฉํ•˜์—ฌ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ˜๋‹ค.
    public UserService(Login login){ //์˜์กด์„ฑ ์ฃผ์ž…, Dependency Injection
        this.login = login;
    }

    @Override
    public void login() {
        login.login();
    }
}
package com.programmers.java.poly;
public class Main {
    public static void main(String[] args) {
       UserService s = new UserService(new KakaoLogin());
       s.login();
    }
}

Dependency Inversion : ์˜์กด์„ฑ ์—ญ์ „

class diagram :: Interface๋ฅผ ์ค‘์‹ฌ์œผ๋กœ Kakao/naver ์™€ UserService์˜ ์˜์กด์„ฑ ์—ญ์ „

 

๋”๋ณด๊ธฐ

โœ… Interface์˜ ๋ชจ๋“  ๋ณ€์ˆ˜๋Š” public static final
โœ… Interface์˜ ๋ชจ๋“  ๋ฉ”์†Œ๋“œ๋Š” public abstract 
โœ… ํƒ€์ž…์œผ๋กœ๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅ. ์ƒ์„ฑ์€ X


์ธํ„ฐํŽ˜์ด์Šค์˜ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ๋“ค ๐Ÿ‘‡ : Java 8 ์ด์ƒ๋ถ€ํ„ฐ ๊ธฐ๋Šฅ ๊ฐ•ํ™”

2. Default method ๊ธฐ๋Šฅ

default ๋ฉ”์†Œ๋“œ : default ํ‚ค์›Œ๋“œ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

๊ฐœ๋…

package com.programmers.java.defualt;

interface MyInterface {
    void method1(); // ์ถ”์ƒ๋ฉ”์†Œ๋“œ
    default void sayHello(){ // default ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง
        System.out.println("Hello World");
    }
}

public class Main implements MyInterface{
    public static void main(String[] args) {
        new Main().sayHello();
    }
//    @Override // ์˜ค๋ฒ„๋ผ์ด๋“œ ๊ฐ€๋Šฅ
//    public void sayHello(){
//        System.out.println("override hello");
//    }
//
    @Override
    public void method1() {
        throw new RuntimeException();
    }
}

ํ™œ์šฉ

 

1. Adapter ์—ญํ• ์„ ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

: interface ๋ฉ”์†Œ๋“œ์ค‘ ์ผ๋ถ€๋งŒ ํ•„์š”ํ•  ๊ฒฝ์šฐ ๋นˆ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด ๋†“์€ Adapter๋ฅผ ๋งŒ๋“ค์–ด ๋†“๊ณ  ์ƒ์†๋ฐ›์œผ๋ฉด ๋นˆ ๋ฉ”์†Œ๋“œ๋“ค์„ ๊ตฌํ˜„ํ•ด๋‘˜ ํ•„์š”์—†์–ด ๊น”๋”ํ•˜๊ฒŒ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

: ํ•˜์ง€๋งŒ class ๋Š” ํ•˜๋‚˜์˜ class ๋งŒ ์ƒ์†ํ•  ์ˆ˜ ์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ด๋ฏธ ์ƒ์†์„ ๋ฐ›์€ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

⇒ Default method๋ฅผ ํ†ตํ•ด adapter๋ฅผ ๋งŒ๋“ค ํ•„์š”์—†์–ด์กŒ๋‹ค.

 

// MyInterfaceAdapter.java
package com.programmers.java.default2;

public class MyInterfaceAdapter implements MyInterface{
    @Override
    public void method1() {
    }
    @Override
    public void method2() {
    }
}
package com.programmers.java.default2;

public class Main {
    public static void main(String[] args) {
        new Service().method1(); // method1๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์Œ
    
}

// Interface ๋ฉ”์†Œ๋“œ๋ฅผ ์ „๋ถ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ Adapter๋ฅผ ๋งŒ๋“ค์–ด(๋นˆ ๋ฉ”์†Œ๋“œ๋กœ ๊ตฌํ˜„๋จ) ์ƒ์†๋ฐ›์•„์„œ ์›ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋งŒ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.
// Adapter๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์ƒ์†์€ ํ•˜๋‚˜๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ด๋ฏธ ๋‹ค๋ฅธ ๊ณณ์„ ์ƒ์† ๋ฐ›์•˜์„ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•œ๋‹ค.
class Service extends MyInterfaceAdapter{
    @Override
    public void method1(){
        System.out.println("Hello");
    }
}
// => ๊ทธ๋Ÿด ๊ฒฝ์šฐ interface method๋ฅผ ์ „๋ถ€ defualt๋กœ ๋งŒ๋“  ํ›„ ์›ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋งŒ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•˜๋ฉด ๊ฐ•์ œ์„ฑ์ด ์—†์–ด ์ฝ”๋“œ๋ฅผ ์›ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋งŒ ๊น”๋”ํ•˜๊ฒŒ ์œ ์ง€ ๊ฐ€๋Šฅ

 

2. interface ์ถ”๊ฐ€๋งŒ์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

package com.programmers.java.default3;

interface Flyable {
    default void fly(){
        System.out.println("fly");
    }
}
interface Swimmable {
    default void swim(){
        System.out.println("swim");
    }
}
interface Wolkable{
    default void wolk(){
        System.out.println(("wolk"));
    }
}
package com.programmers.java.default3;
class Duck implements Flyable,Wolkable,Swimmable{}
class Swan implements Flyable,Swimmable{}

public class Main {
    public static void main(String[] args) {
        new Duck().fly();
        new Swan().swim();
    }
}

 

3. static ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋‹ค. : ํ•จ์ˆ˜ ์ œ๊ณต์ž(๊ทธ๋ฆ‡)๊ฐ€ ๋œ๋‹ค. → ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

package com.programmers.java.default3;

interface Ability{
    static void sayHello(){
        System.out.println("Hello");
    }
}

public class Main {
    public static void main(String[] args) {
        Ability.sayHello();
    }
}

 

 

3. Functional Interface

๋ฉ”์†Œ๋“œ : class์— ์ข…์†๋œ ํ•จ์ˆ˜

  • ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•˜๋‚˜๋งŒ ์กด์žฌํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค @FuncionalInterface
package com.programmers.java.func;

@FunctionalInterface
public interface MyRunnable {
    void run(); // ์ถ”์ƒ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•˜๋‚˜๋ฐ–์— ์—†๋Š” ๋ฉ”์†Œ๋“œ == ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค
}

@FunctionalInterface
interface MyMap{
    void map();
    default void sayHello(){
        System.out.println("Hello World");
    }
    static void sayBye(){
        System.out.println("Bye World");
    }
}

 

 

4. Lambda ํ‘œํ˜„์‹

โž• ์ธํ„ฐํŽ˜์ด์Šค ์ž„์‹œ์ƒ์„ฑ

  • ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ธํ„ฐ์ฒด์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ตฌํ˜„์„ ๋ฐ”๋กœ ์ •์˜ํ•œ๋‹ค.

: ์›๋ž˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„  ๋ฌด์กฐ๊ฑด class๋ฅผ ์ƒ์„ฑํ•ด implements ํ•ด์ค˜์•ผ new๋ฅผ ํ†ตํ•ด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ, ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ–ˆ๋‹ค.

⇒ ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์ด๋ฆ„์—†๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด์—ฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

package com.programmers.java.func;

public class Main {
    public static void main(String[] args) {
        new MyRunnable(){
            @Override
            public void run() {
                System.out.println("run");
            }
        }.run();
    }
}

 

: ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ต๋ช…์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ฉ”์†Œ๋“œ๋„ ์ต๋ช…์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์—†์„๊นŒ?

  • ์ต๋ช… ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ⇒ ๋žŒ๋‹ค ํ‘œํ˜„์‹
  • ์ต๋ช… ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๋ฐฉ๋ฒ•.
  • functional interface์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
package com.programmers.java.func;

public class Main2 {
    public static void main(String[] args) {
        // 1. functional interface๋ฅผ ์ต๋ช… ๊ฐ์ฒด๋กœ ๋งŒ๋“ค ๊ฒฝ์šฐ ๋ฌด์กฐ๊ฑด ํ•˜๋‚˜์˜ method๋ฅผ override๋ฅผ ํ•ด์ค˜์•ผํ•œ๋‹ค.
        MyRunnable r = new MyRunnable() {
            @Override
            public void run() {
                System.out.println("run");
            }
        };
        r.run();

        // 2. ์–ด์ฐจํ”ผ ํ•˜๋‚˜์˜ ๋ฉ”์†Œ๋“œ๋งŒ override ํ•ด์ค˜์•ผํ•˜๊ฒŒ ๋•Œ๋ฌธ์— ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. => ์ต๋ช…๋ฉ”์†Œ๋“œ
        // ๊ตฌํ˜„๋ถ€๊ฐ€ ํ•œ์ค„์ผ ๊ฒฝ์šฐ {} ์ƒ๋žต๊ฐ€๋Šฅ. return๋„ ์ƒ๋žต๊ฐ€๋Šฅ
        MyRunnable r2 = () -> {
            System.out.println("run~~~");
        };
    }
}

 

  • ๋ฉ”์†Œ๋“œ ๋ ˆํผ๋Ÿฐ์Šค

: ๋žŒ๋‹ค ํ‘œํ˜„์‹์—์„œ ์ž…๋ ฅ๋˜๋Š” ๊ฐ’์„ ๋ณ€๊ฒฝ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

: ์ž…๋ ฅ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜์ง€ ๋ง๋ผ๋Š” ์˜์ง€์˜ ํ‘œํ˜„ ๋ฐฉ์‹์ด๊ธฐ๋„ ํ•˜๋‹ค. → ๊ฐœ๋ฐœ์ž์˜ ๊ฐœ์ž…์„ ์ฐจ๋‹จํ•˜์—ฌ ์•ˆ์ „์„ฑ ์–ป๊ธฐ

: ์ตœ์ข…์ ์œผ๋กœ ์ ์šฉ๋  ๋ฉ”์†Œ๋“œ์˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ง€์ •ํ•ด ์ฃผ๋Š” ํ‘œํ˜„ ๋ฐฉ์‹

MyConsummer c = (str) -> System.out.println(str);

MyConsummer c = System.out::println;

 

  • ์ œ๋„ค๋ฆญ

: ์ธ์ž ํ˜น์€ ๋ฆฌํ„ด๊ฐ’์„ ์œ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

: reference type๋งŒ ์‚ฌ์šฉ๊ฐ€๋Šฅ

@FunctionalInterface
public interface MyMapper<IN, OUT> {
    OUT map(IN s);
}
@FunctionalInterface
public interface MySupplier<T> {
    T supply();
}

public class Main {
    public static void main(String[] args) {
        MySupplier<String> s = () -> "Hello";
        MyMapper<String,Integer> m = (str) -> str.length(); //reference type๋งŒ ๊ฐ€๋Šฅํ•ด์„œ Integer
				Systme.out.println(m.map(s.supply()));
    }
}

 


์œ„์™€ ๊ฐ™์ด ์ž์ฃผ ํ™œ์šฉํ• ์ˆ˜ ์žˆ๋Š” Functional Interface๋“ค์€ java.util.function์—์„œ ์ œ๊ณต๋œ๋‹ค.

https://docs.oracle.com/javase/8/docs/api/

 

Java Platform SE 8

 

docs.oracle.com

ํ™œ์šฉ ์˜ˆ

package com.programmers.java.lambda;

import java.util.function.Consumer;
import java.util.function.Predicate;

public class Main3 {
    public static void main(String[] args) {
        new Main3().filteredNumbers(30,
                i -> i % 3 == 0 && i > 0,
                System.out::println
        );
       // ๊ธฐ๋Šฅ์„ ํ˜ธ์ŠคํŠธ์—๊ฒŒ ๋งก๊ฒจ ๋‹ค์–‘ํ•˜๊ฒŒ ์‚ฌ์šฉ์žํ™” ๊ฐ€๋Šฅํ•˜๋‹ค.
    }
    void filteredNumbers(int max, Predicate<Integer> p, Consumer<Integer> c) {
        for (int i = 0; i < max; i++) {
            if (p.test(i)) c.accept(i);
        }
    }
}

๋Œ“๊ธ€