인터페이스부터 시작되는 표현법 이야기

어겐어갠·2022년 3월 23일
0

인터페이스는 추상클래스와 비슷하면서 다르다.

가장 큰 차이점중의 하나는 구현이 강제된다는 점과 구현부가 존재하지 않는다는 점이었다.

인터페이스의 기능

  1. 구현 강제(모든 메서드가 추상메서드)
  2. 다형성을 제공 -> 의존성 역전
  • 구현이 강제되었을 때 생기는 문제점

class1은 interface1의 method1만 사용하고싶다.
but method2,3...이 있다면 이들을 강제로 구현해야할 필요가 생겨버린다.

  • 이를 대처하기 위해 Adapter가 등장하는데..

Adapter란 interface1을 Impl 받는 AdapterClass를 만들고 Class1이 상속받는 것이다.
이로써 Class1은 interface1의 모든 메서드를 구현화할 의무에서 벗어나게 된다.

  • 그런데 만약? Class1이 이미 다른 클래스를 상속받고있다면?
    java에서는 다중상속이 불가능하다.

다행히 java8부터 default Method가 생겼다.

default Method

  1. 인터페이스가 구현체를 가질 수 있게됐다. (default)
  2. 이로써 Adapter 역할을 수행할 수 있다.
  3. static 메소드를 통해 함수를 제공할 수 있다.
  4. 인터페이스만으로 기능을 확장이 가능하다.

Functional Interface

  1. 추상메소드가 1개인 인터페이스(default, static의 유무에 상관없이 1개의 추상메소드만 지닌다면 ok)
  2. @FunctionalInterface

interface를 구현하기위해서는 클래스를 통해서만 가능했었는데...
클래스를 매번 생성하는 것도 일이었던 것을

익명클래스

클래스로 Impl받지않고 바로 new를 통해 interface를 생성하고 override받아 구현이 가능해졌다.

문제점은 override받은 메서드를 구현하는데 표현식이 너무나 길고 복잡했다.
만약 functional interface의 경우 어차피 구현해야할 메서드는 1개임에도 불구하고

lambda 표현식

  1. 익명 메서드를 사용해 인터페이스 인스턴스 생성 표현을 간결하게 한다.
  2. functional interface에서는 가능하다. (만약 구현해야할 메서드가 2개 이상일 경우 무엇을 구현해야할지 모르기때문에 lambda로 표현할 수 없다.

파이썬에서도 가끔씩 람다 표현식을 사용해왔는데 map으로 list를 돌면서 각 index의 값을 변화시키는데 기계적으로 사용했을 뿐 식이 왜 ()-> 방식인지는 알지 못했었다. 영상 강의에서 override된 복잡한 식을 필요없는 부분을 덜어내고 덜어내서 최종적으로 lambda 표현식으로 완성하는 과정을 보여주어 이해가 더 쉬웠다.

메서드 레퍼런스

만약 람다 표현식에서 입력값이 변경없이 사용되는 경우 사용할 수 있다.
장점으로는 개발자의 개입을 차단함으로써 협업시 안정성을 높일 수 있고, 값을 변경하지 말라는 일종의 경고 표현식으로도 생각할 수 있다.

제네릭으로 자주 사용되는 인터페이스
https://docs.oracle.com/javase/8/docs/api/

Consummer< T > / void / accept(T t)
Function< T, R > / R / apply(T t)
Supplier< T > / T / get()
BiFunction< T, U, R > / R /apply(T t)
Predicate< T > / boolean / test(T t)

profile
음그래

0개의 댓글