Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags more
Archives
Today
Total
관리 메뉴

까마귀코딩.log

백기선 자바스터디 08주차 본문

백기선 자바스터디

백기선 자바스터디 08주차

까마귀코딩 2023. 1. 31. 17:59
더보기
왜? 라는 생각을 달고 살자!

<< 총 15주차 까지 진행되며 주어지는 키워드를 가지고 블로그에 정리하며 공부하는 스터디 입니다 ! >>


목표

자바의 인터페이스에 대해 학습하세요.

학습할 것 (필수)

  • 인터페이스 정의하는 방법
  • 인터페이스 구현하는 방법
  • 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
  • 인터페이스 상속
  • 인터페이스의 기본 메소드 (Default Method), 자바 8
  • 인터페이스의 static 메소드, 자바 8
  • 인터페이스의 private 메소드, 자바 9

 

 


인터페이스 정의하는법 !


 

인터페이스 정의하는 방법 ?!?

 
  1. 클래스간 결합(느슨한 결합)을 낮춰준다. 인터페이스를 통해서 여러 클래스에서 각각 구현하여 사용할 수 있게된다.
  2. 표준화가 가능하다. 어떤 기능을 구현해야 하는지를 인터페이스를 통해 추론할 수 있다.

 

 

 

 

그래서 뭔뜻인데 ..

객체 지향 프로그래밍의 추상화를 배우고 추상 클래스를 접해봤다면 ?

그 다음 접해보는 것이 인터페이스(Interface) 일 것이다.

인터페이스는 간단히 말하자면 프로그램을 설계하고 조금 더 유연한 프로그램을 만드는 기법을 말한다.


인터페이스는 추상화와 상속과 더불어 다형성이라는 객체 지향의 특징을 구현하는 핵심이다.


 

 

 

 

 

 

 


인터페이스 구현하는법 !


 

 

인터페이스 일부 구현 (추상 클래스)

  • 만일 클래스가 구현하는 인터페이스의 메서드 중 일부만 구현한다면  abstract 를 붙여서 추상 클래스로 선언해야 한다.
  • 어찌 보면 당연한게 인터페이스의 추상 메서드 멤버를 그대로 상속받기 때문에, 인터페이스를 상속한 클래스에서 메서드 구현을 안한다면, 곧 추상 메서드를 가진 추상 클래스가 되기 때문이다.

 

 

 

개발 코드가 직접 객체의 메소드를 호출하지 않고, 인터페이스를 이용하는 이유는?

인터페이스는 하나의 객체가 아니라 여러 객체들과 사용이 가능하다. 때문에 개발 코드의 변경 없이 어떤 객체를 사용하느냐에 따라 실행 내용과 리턴값을 다양화 할 수 있는 장점이 있다.

 

 

 

그래서

인터페이스를 정의하는 방법 ?? 

 

 interface 키워드를 사용한다 

[public] interface 인터페이스명 {}

우와간단!

 

 

 

 

 

 

 

ex >  TV 인터페이스

인터페이스의 구성 멤버: 상수, 메소드 (인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없다. )

<->

클래스의 구성 멤버: 필드, 생성자 , 메소드

 

 

 

 

 

 

 

 

자바 8부터 메소드 실행 블록 작성이 가능 디폴트 메소드 정적 메소드 선언이 가능해졌다 !!

interface 인터페이스명{
    
    //상수
    타입 상수명 = 값;
    
    //추상 메소드
    타입 메소드명(매개변수, ...);
    
    //디폴트 메소드
    default 타입 메소드명(매개변수, ...){...}
        
        //정적 메소드
        static 타입 메소드명(매개변수, ...){...}
        
}

 

 

인터페이스의 상수 필드  

클래스에서 상수는 public static final로 선언하지만, interface에서는 이를 생략 가능하다.

생략하더라도 자동적으로 컴파일 과정에서 붙는다.

[public static final] 타입 상수명 = 값;

 

상수명은 대문자로 작성하되, 서로 다른 단어는 언더바(_)로 연결하는 것이 관례

public interface TV {
    
    public static final int MAX_CHANNEL = 100;
    int MIN_CHANNEL = 0; // public static final 생략 가능
    
}

 

 

 

 

인터페이스의 추상 메소드 

 

인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행된다. 때문에 인터페이스의 메소드는 실행 블록이 필요 없는 추상 메소드로 선언한다. 

 

 

 

 

인터페이스에 선언된 추상 메소드는 모두 public abstract의 특성을 갖기 때문에 이를 생략해도 자동적으로 컴파일 과정에서 붙는다.

추상 메소드: 리턴 타입, 메소드명, 매개변수만 기술하고 중괄호 ’{}’를 붙이지 않는 메소드

public interface TV {
    
    //상수
    int MAX_CHANNEL = 1000;
    int MIN_CHANNEL = 0;
    
    
    
    //추상 메소드
    public abstract void turnOn();
    public abstract void turnOff();
    void setChannel(int channelNum); //public abstract 생략가능
    
}

 

인터페이스의 디폴트 메소드(기본 메소드, Default Method)

- 인터페이스에 선언되지만 실제 실행하는 구현 코드를 작성하는 메소드

- 자바 8에 추가된 인터페이스의 새로운 멤버

 

 

 

 

디폴트 메서드가 만들어진 이유 ??? 

인터페이스를 쉽게 바꾸어서 미래에 프로그램이 쉽게 변화할 수 있는 환경을 제공하기 위함이다

 

 

 

이를 이해하기 위해 사례를 한 가지 들어보자.

자바 8 이전에는 List<T>가 stream이나 parallelStream 메서드를 지원하지 않았다.

이것을 지원하기 위한 간단한 해결책은 ?? 

1. List<T>가 구현하고 있는 Collection 인터페이스에 stream 메서드를 추가하기 

2. ArrayList 클래스에서 메서드를 구현하기 !!

 

하지만 이 방법은 사용자에게 너무 고통을 안겨준다.

이미 Collection 인터페이스를 구현하는 많은 컬렉션 프레임워크들이 존재하기 때문에

인터페이스에 새로운 메서드를 추가하면 인터페이스를 구현한 모든 클래스에서 새로 추가된 메서드를 구현해야 했다.

 

 

 

그래서

자바 개발자들을 구현을 고치지 않고도 이미 공개된 인터페이스를 변경할 수 있는 방법을 생각했다.

바로 구현 클래스에서 구현하지 않아도 되는 메서드를 인터페이스에 추가하는 것이었다.

이 기능의 메서드 본문은 클래스 구현이 아니라 인터페이스의 일부로 포함되기 때문에 디폴트 메서드라고 부르게되었다.

 

그니까 디폴트 메소드를 인터페이스에 추가하라는거네 . .

 

 

 

 

디폴트 메소드를 정의하는 방법 ?

 

->  default 키워드를 return 타입 앞에 표시

public 특성을 갖기 때문에 이를 생략해도 자동적으로 컴파일 과정에 붙게 된다.

[public] default 리턴타입 메소드명(매개변수, ...) {...}
public interface TV {
    
    //상수
    int MAX_CHANNEL = 1000;
    int MIN_CHANNEL = 0;
    
    //추상 메소드
    void turnOn();
    void turnOff();
    void setChannel(int channelNum);
    
    //디폴트 메소드
    default void setMute(boolean mute){
        
        if(mute){
            System.out.println("무음 처리");
        }else{
            System.out.println("무음 해제");
        }
    }
}

 

Q. 인터페이스의 defulat, static 메소드의 등장으로 추상클래스는 필요 없어졌을까?

public interface Keyboard {
    void ledOn();
    void ledOff();
    void touch();
}
public abstract class Computer implements Keyboard{
    private String message;
    
    @Override
    public void touch(){
        System.out.println(message);
    }
    
    public void setMessage(String message){
        this.message = message;
    }
}

추상 클래스에서는 위 코드의 String message 과 같이 변수를 선언할 수 있다. 인터페이스는 상수만 선언이 가능하다. 즉, 작성하려는 코드의 상태를 변수로 관리해야한다면 추상 클래스를 사용해야한다.

 

 

 

 

 


인터페이스 레퍼런스를 통해 구현체를 사용하는법 !


 

 

 

인터페이스를 구현하는 방법

 

개발 코드가 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출한다. 객체는 인터페이스에서 정의된 추상 메소드와 동일한 메소드 이름, 매개 타입, 리턴 타입을 가진 실체 메소드를 가지고 있어야 한다. 

 

이러한 객체를 인터페이스의 구현(implement) 객체라고 하고, 구현 객체를 생성하는 클래스를 구현 클래스라고 한다. 

 

구현 클래스는 인터페이스 타입으로 사용할 수 있음을 알려주기 위해 클래스 선언부에 implements 키워드를 추가하고 인터페이스명을 명시해야 한다. 그리고 인터페이스에 선언된 추상 실체 메소드를 선언한다.

 

public class 구현클래스명 implements 인터페이스명{
    //인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}

 

이때 다음과 같은 주의 사항을 명심하자. 

 

 🖍 실체 메소드를 작성할 때 인터페이스의 모든 메소드는 기본적으로 public 접근 제한을 갖기 때문에 public보다 낮은 접근 제한으로 작성할 수 없다.

🖍 실체 메소드 위에 @Override 어노테이션을 붙인다. 이렇게 하면 추상 메소드에 대한 정확한 실체 메소드인지 컴파일러가 체크한다.

 

 

 

 

 

 

 


인터페이스 상속 !


 

 

인터페이스 상속

 

인터페이스도 다른 인터페이스를 상속할 수 있다. 인터페이스는 클래스와 달리 다중 상속을 허용한다.

 

public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2{...}

 

하위 인터페이스를 구현하는 클래스는 하위 인터페이스의 메소드와 상위 인터페이스의 모든 추상 메소드에 대한 실체 메소드를 가지고 있어야 한다. 때문에 구현 클래스로부터 객체를 생성하면 다음과 같이 하위 및 상위 인터페이스 타입으로 변환이 가능하다.

 

하위인터페이스 변수 = new 구현클래스(...);
상위인터페이스1 변수 = new 구현클래스(...);
상위인터페이스2 변수  = new 구현클래스(...);

 

하위 인터페이스로 타입 변환이 되면 상,하위 인터페이스에 선언된 모든 메소드를 사용할 수 있다. 상위 인터페이스로 타입 변환되면 상위 인터페이스에 선언된 메소드만 사용 가능하다. 

 

public interface InterfaceA {
    public void methodA();
}

public interface InterfaceB {
    public void methodB();
}

public interface InterfaceC extends InterfaceA, InterfaceB {
    public void methodC()
}

public class Implementation implements InterfaceC{
    
    
    @Override
    public void methodC() {
        System.out.println("InterfaceC - methodA() 실행");
    }
    
    @Override
    public void methodB() {
        System.out.println("InterfaceB - methodA() 실행");
    }
    
    @Override
    public void methodA() {
        System.out.println("InterfaceA - methodA() 실행");
    }
}
public class Main {
    
    public static void main(String[] args){
        
        Implementation impl = new Implementation();
        InterfaceA ia = impl;
        ia.methodA();
        InterfaceB ib = impl;
        ib.methodB();
        
        InterfaceC ic = impl;
        ic.methodA();
        ic.methodB();
        ic.methodC();
    }
}

 

🔔결과

 

 

 


인터페이스의 기본메소드 ! (default ), java 8


 

Java - Interface의 Default Methods 이해하기

Java8에서 인터페이스에 디폴트 메소드(Default methods)라는 것이 생겼다 !

인터페이스는 메소드 정의만 할 수 있고 구현은 할 수 없었습니다만,

Java8부터 디폴트 메소드라는 개념이 생겨 구현 내용도 인터페이스에 포함시킬 수 있었음

Default methods에 대해서 알아보자 !

 

 

1. Default methods를 정의하는 방법

일반적으로 인터페이스를 구현한거

public interface Vehicle {
    public void doSomething(int n);
}

 

 

디폴트 메소드를 사용하면 구현내용도 인터페이스에 포함시킬 수 있다.

아래 코드처럼 메소드 이름 앞에 default 키워드를 입력하고 구현 내용을 추가헤 !

public interface Vehicle {
    public default void doSomething(int n) {
        System.out.println("doSomething(Vehicle)");
    }
}

 

 

 

디폴트 메소드가 구현된 인터페이스도 상속받을 수 있습니다. 다음 코드는 VehicleChild가 Vehicle를 상속받는 코드이다

public interface Vehicle {
    public default void doSomething(int n) {
        System.out.println("doSomething(Vehicle)");
    }
}

public interface VehicleChild extends Vehicle {
}

Vehicle는 VehicleChild의 디폴트 메소드 구현도 함께 상속받게 되는것 !

 

 

 

 

 

 

 

 

 

 


인터페이스 static 메소드 , java 8


인터페이스의 정적 메소드 (static) ??

 

- 디폴트 메서드와 같이 실제 실행되는 구현 코드를 작성하는 메서드를 말한다 !

디폴트 메서드와 달리 객체가 없어도 인터페이스만으로 호출 가능 !!

- 자바 8 부터 추가되었다

 

인터페이스의 정적 메소드를 정의하는 방법 ?

 형태는 클래스의 정적 메소드와 동일 하지만 public 특성을 갖기 때문에 public을 생략하더라도 자동으로 컴파일 과정에 붙는다.

[public] static 리턴타입 메소드명(매개변수, ...) {...}

 

public interface TV {
    
    //상수
    int MAX_CHANNEL = 1000;
    int MIN_CHANNEL = 0;
    
    
    //추상 메소드
    void turnOn();
    void turnOff();
    void setChannel(int channelNum);
    
    
    
    //디폴트 메소드
    default void setMute(boolean mute){
        if(mute){
            System.out.println("무음 처리");
        }else{
            System.out.println("무음 해제");
        }
    }
    
    //정적 메소드
    static void printMaxChannel(){
        System.out.println("채녈은 "+MAX_CHANNEL+"번까지 존재합니다.");
    }
}

 

 

 

 

 


인터페이스 private 메소드, java9


 

 

 

인터페이스의 private 메소드

 

자바 8에서 인터페이스 메소드는 특정 기능을 처리하는 내부 메소드도 외부에 공개되는 public method로 만들어야 하는 단점이 있었다.

 

하지만 인터페이스를 구현하는 다른 인터페이스 또는 클래스가 해당 메소드에 액세스하거나 상속 하는 것을 원하지 않는 경우가 있다. 이를 위해 자바 9에서는 인터페이스에 메소드에 private을 사용할 수 있도록 했다.