6. INHERITANCE AND INTERFACE_15 INTERFACE

jaegeunsong97·2022년 11월 23일
0

[Inflearn] 홍팍 자바

목록 보기
15/15

홍팍이는 개발자다. 동시에 강사이며, 친구이다. 상황에 따라 다양한 역할을 수행한다.

프로그램에서 또한 마찬가지다. 한 객체가 다양한 역할을 수행할 수 있다. 이를 위한 개념. 인터페이스를 학습해보자.
인터페이스란
인터페이스 정의 및 구현
인터페이스의 장점

Interface

interface >> 인터페이스란, 역할을 부여하는 것이다.
character >> 인터페이스는 추상 메소드로 구성된다. 추상 메소드란, 중괄호 내부가 없는 껍데기 메소드이다.
example >> 스마트폰은 알람, 전화기, 메신저의 역할을 한다.

Definition interface and implement

code structure >>

interface NAME {
  // 프로토타입 메소드들..
}

example code >> Alarm 인터페이스 만들어보자. 그 기능으로는 비프음 내기와 음악 재생을 추가한다. 메소드에 중괄호가 없음을 주의하자. 이러한 메소드를 추상 메소드라 한다.

interface Alarm {
  public void beep(); // 추상메소드
  public void playMusic(); // 추상메소드
}

declare interface implement >> 위에서 만든 인터페이스를 클래스에 구현하자. 이를 위해 implements 키워드를 사용한다.

// SmartPhone 클래스가 Alarm 역할을 수행하기로 함!
class SmartPhone implements Alarm {
  // 내부 구현 생략..
}

proto type method overriding >> 이제 Alarm 인터페이스의 모든 추상 메소드를 재정의(오버라이딩) 해야 한다. 중괄호 내부가 없기 때문이다.

class SmartPhone implements Alarm {
  // 프로토타입 메소드를 재정의!
  public void beep() {
    System.out.println("삐~ 삐삑, 삐비비빅!");
  }
  // 프로토타입 메소드를 재정의!
  public void playMusic() {
    System.out.println("아침 해가 빛나는~ 끝이 없는 바닷가!");
  }
}

Advantage of interface

clearity for programming design >> 인터페이스를 사용하면 프로그램 설계가 보다 명확해 진다.
up-casting relationship >> 서로 다른 객체들이 같은 인터페이스를 구현한다면, 인터페이스를 타입으로 하여 업캐스팅 할 수 있다.

polymorphism >> 여러 인터페이스를 구현하게 함으로써, 한 객체를 여러 타입으로 해석할 수 있게 된다. 이러한 특징을 다형성이라 한다.

1) Interface definition and implement

interface >> 인터페이스란, 하나의 역할을 정의하는 것입니다.

make interface >> 예를 들어, 경보음을 위한 Alarm이라는 역할은 아래와 같이 만들 수 있습니다.

interface Alarm {
  // 내용 생략..
}

proto type method >> Alarm 인터페이스는 경보음을 내기위해 어떠한 기능을 해야할까요? 그 대략적인 틀을 프로토타입(추상) 메소드를 통해 정의합니다. 여기서 프로토타입 메소드란, 중괄호 내용이 없는 껍데기 메소드입니다.

interface Alarm {
  // 비프음을 냈으면 좋겠어? 어떻게? 그건 나중에 정할께!
  public void beep();
  // 음악을 재생했으면 좋겠어! 어떻게? 그건 나중에 정할께!
  public void playMusic();
}

implements class >> 인터페이스를 통해 역할을 정의했다면, 이를 클래스에게 부여할 수 있습니다. 이러한 클래스를 구현체라고 합니다.

// SmartPhone 클래스는 Alarm 인터페이스를 구현하기로 한다!
class SmartPhone implements Alarm {
  내용 생략..
}

클래스가 특정 인터페이스를 구현(implements)하기로 했다면, 인터페이스를 구성하는 프로토타입(추상) 메소드를 반드시 오버라이딩(재정의)해야 합니다.

class SmartPhone implements Alarm {
  // beep음은 이렇게 낼거야!
  public void beep() {
    System.out.println("삐빅~ 삐비비비빅!");
  }
  // 음악 재생은 이렇게 할거야!
  public void playMusic() {
    System.out.println("동해물과 백두산이~🎶");
  }
}

CODE

public class SmartPhoneTest {
  public static void main(String[] args) {
    // 객체 생성
    SmartPhone sp = new SmartPhone("아이폰", "010-0000-0000");
    // 전화 걸기
    sp.call("010-1234-5678");
    // 전화벨이 울림
    sp.ring();
  }
}
interface Phone {
  // targetNumber로 전화를 걸거야! 어떻게? 그건 아직 몰라!
  public void call(String targetNumber);
  // 전화벨이 울릴거야! 어떻게? 그건 아직 몰라!
  public void ring();
}
class SmartPhone implements Phone {
  protected String name;
  protected String phoneNumber;
  public SmartPhone(String name, String phoneNumber) {
    this.name = name;
    this.phoneNumber = phoneNumber;
  }
  /* Phone 인터페이스의 모든 프로토타입 메소드를 구현하시오. */  
  public void call(String targetNumber){
    System.out.printf("%s로 전화를 겁니다!", targetNumber);
  }
  public void ring(){
    System.out.println("전화벨이 울립니다~");
  }
}

2) Interface definition and implement-2

give interface base structure >> 인터페이스는 특정 역할에 대한 대략적인 틀만 정의합니다. 아래는 Healer 인터페이스의 예입니다.

// 힐러 역할
interface Healer {
  public void healing(); // 체력 회복
  public void shield();  // 보호막 생성
}

typing detail code >> 이제 해당 인터페이스를, 특정 클래스에 부여해보도록 하겠습니다. 이때 사용하는 키워드가 바로 implements 입니다.

// 마법사 클래스에게 Healer 인터페이스를 부여
class Wizard implements Healer { ... }

특정 인터페이스를 부여받은 클래스는, 반드시 프로토타입 메소드를 오버라이딩(재정의) 해주어야만 합니다. 인터페이스는 껍데기 메소드로 이루어져있어, 실행될 수 없기 때문입니다. 따라서 아래와 같이 중괄호 내부를 정의해야 합니다.

class Wizard implements Healer {
  // 메소드 오버라이딩(재정의)
  public void healing() {
    System.out.println("체력을 회복시킵니다!");
  }
  // 메소드 오버라이딩(재정의)
  public void shield() {
    System.out.println("보호막을 생성합니다!");
  }
}

CODE

public class SmartPhoneTest2 {
  public static void main(String[] args) {
    // 객체 생성
    SmartPhone s = new SmartPhone("아이폰");
    // 비프음 내기
    s.beep();
    // 음악 재생하기
    s.playMusic("상어송");
  }
}
interface Alarm {
  public void beep();                  // 비프음
  public void playMusic(String title); // 음악 재생
}
class SmartPhone implements Alarm {
  private String name; // 모델명
  public SmartPhone(String name) {
    this.name = name;
  }
  /* Alarm 인터페이스의 추상 메소드를 재정의하시오. */
  public void beep(){
    System.out.println("삐빕! 삐비비빕~!");
  }
  public void playMusic(String title){
    System.out.printf("[%s]을 재생합니다..!", title);
  }
}

3) Interface and polymorphism

do lots of role >> 하나의 클래스가 여러 개의 인터페이스를 구현할 수 있습니다.

예를 들어, 스마트폰(SmartPhone) 클래스에 알람(Alarm) 및 전화(Phone) 그리고 메신저(Messenger)의 역할을 동시에 부여하는 경우, implements 키워드 뒤쪽에 인터페이스들을 쉼표로 구분하여 적어주면 됩니다. 인터페이스를 구현하기로 선언하였다면, 반드시 프로토타입 메소드들을 오버라이딩해야 함을 잊지 마세요.

class SmartPhone implements Alarm, Phone, Messenger {
  // 내부 생략..
}

이제 SmartPhone은 알람 및 전화기, 또는 메신저 타입으로 해석(업캐스팅)될 수 있습니다.

// 스마트폰 객체 생성
SmartPhone sp = new SmartPhone();
// 스마트폰을 다양하게 해석(업캐스팅 - 상위 타입으로 해석)
Alarm a = sp; // 스마트폰은 알람이다. (O)
Phone p = sp; // 스마트폰은 전화기이다. (O)
Messenger m = sp; // 스마트폰은 메신저이다 (O)

polymorphism >> 이렇게 하나의 객체가 다양한 타입으로 해석되는 것을 다형성(Polymorphism)이라 합니다.
CODE

public class Polymorphism {
  public static void main(String[] args) {
    // 성기사 객체 생성
    HolyKnight uther = new HolyKnight("우서", 180);
    // 탱커로서의 역할 수행
    Tanker t = uther;
    t.increaseHp();
    // 힐러로서의 역할 수행
    Healer h = uther;
    h.heal();
  }
}
interface Tanker {
  public void increaseHp();
}
interface Healer {
  public void heal();
}
/* 1. 탱커와 힐러 역할을 부여하세요. */
class HolyKnight implements Tanker, Healer{
  private String name;
  private int hp;
  public HolyKnight(String name, int hp) {
    this.name = name;
    this.hp = hp;
  }
  /* 2. Tanker의 메소드를 오버라이딩하세요. */
  public void increaseHp(){
    System.out.printf("전체 체력 +50 증가시킵니다." );
  }
  /* 3. Healer의 메소드를 오버라이딩하세요. */
  public void heal(){
    System.out.printf("체력을 +30 회복합니다.");
  }
}

4) Interface and polymorphism-2

do lots of role >> 하나의 클래스가 여러 개의 인터페이스(역할)를 구현할 수 있습니다. 이는 마치, 홍팍이가 아들/강사/개발자의 역할을 수행하는 것과 같습니다.

interface AAA {
  public void aaa();
}
interface BBB {
  public void bbb();
}
interface CCC {
  public void ccc();
}
// Foo 클래스는 총 3가지 역할(AAA, BBB, CCC)을 수행!
class Foo implements AAA, BBB, CCC {
  ...
}

interpret as interface type >> 위 코드에서 Foo 클래스의 객체는 각 인터페이스 타입으로도 해석 가능합니다. 홍팍이가 집에서는 아들, 학원에서는 강사, 회사에서는 개발자인 것처럼 말입니다.

// 객체 생성
Foo obj = new Foo();
// 인터페이스 타입으로 업캐스팅(해석)
AAA a = obj;
BBB b = obj;
CCC c = obj;

인터페이스 타입으로 해석된 객체는, 해당 인터페이스의 메소드만 수행 가능합니다.

a.aaa(); // O
b.bbb(); // O
c.ccc(); // O
a.bbb(); // X
b.aaa(); // X
c.bbb(); // X

CODE

public class VariousRoles {
  public static void main(String[] args) {
    // HongPark 객체 생성
    HongPark park = new HongPark();
    // 각 직업으로 변신
    Developer devPark = park;
    Instructor instPark = park;
    Masseur masPark = park;
    /* 3. 직업별 메소드를 호출하여 코드를 완성하세요. */
    devPark.programming("Java");
    instPark.teach("자료구조");
    masPark.massage();
  }
}
interface Developer {
  public void programming(String lang);
}
interface Instructor {
  public void teach(String subject);
}
interface Masseur {
  public void massage();
}
/* 1. 홍팍 클래스에 개발자, 강사, 마사지사 역할을 부여하세요. */
class HongPark implements Developer, Instructor, Masseur{
  private String name = "홍팍";
  /* 2. 구현하기로 한 인터페이스의 메소드를 오버라이딩 하세요.*/
  public void programming(String lang){
    System.out.printf("%s -> %s 프로그래밍 중!", this.name, lang);
  }
  public void teach(String subject){
     System.out.printf("%s -> %s 수업 중!", this.name,subject);
  }
  public void massage(){
     System.out.printf("%s -> 마사지 중!",this.name);
  }
}

5) Interface and upcasting

interpret as parent type?? >> 업캐스팅(up-casting)이란, 자식 객체를 부모의 타입으로 해석하는 것을 말합니다.

이와 마찬가지로, 인터페이스를 구현하는 객체는 인터페이스 타입으로 업캐스팅 될 수 있습니다.

groupping >> 전혀 다른 객체들일지라도 같은 인터페이스를 구현하였다면, 업캐스팅을 통하여 그룹화가 가능합니다.

// 다양한 객체 생성
Bird bird = new Bird();
Helicopter copter = new Helicopter();
Rocket rocket = new Rocket();
// 인터페이스 타입으로 그룹화
Flyable[] flyableThings = { bird, copter, rocket };

CODE

public class ObjectGrouping {
  public static void main(String[] args) {
    // 다양한 객체 생성
    Bird bird = new Bird();
    Helicopter copter = new Helicopter();
    Rocket rocket = new Rocket();
    // 인터페이스 타입으로 그룹화
    Flyable[] flyableThings = { bird, copter, rocket };
    // 모든 날것들을 날림
    for (int i = 0; i < flyableThings.length; i++) {
      Flyable temp = flyableThings[i];
      temp.fly();
    }
  }
}
interface Flyable {
  public void fly();
}
class Bird implements Flyable {
  /* 1. fly() 메소드를 오버라이딩 하세요. */
  public void fly(){
    System.out.println("<새>가 날개를 퍼덕이며 날아갑니다!");
  }
}
class Helicopter implements Flyable {
  /* 2. fly() 메소드를 오버라이딩 하세요. */
  public void fly(){
    System.out.println("<헬기>가 프로펠러를 힘차게 돌리며 날아갑니다!");
  }
}
class Rocket implements Flyable {
  /* 3. fly() 메소드를 오버라이딩 하세요. */
  public void fly(){
    System.out.println("<로켓>이 제트 엔진을 분출하며 날아갑니다!");
  }
}

6) Interface and arraylist

interface as a type >> 우리는 앞서 인터페이스 타입으로 업캐스팅이 가능함을 배웠습니다.

따라서 다양한 하위 객체들을 상위 인터페이스 타입으로 ArrayList에 저장 가능합니다.

// Flyable 타입을 저장할 ArrayList 생성
ArrayList<Flyable> list = new ArrayList<Flyable>();
// 인터페이스를 통한 다양한 하위 객체들을 저장
Flyable b = new Bird();
Flyable h = new Helicopter();
Flyable r = new Rocket();
list.add(b);
list.add(h);
list.add(r);

CODE

import java.util.ArrayList;
public class InterfaceType {
  public static void main(String[] args) {
    // 객체 생성
    ArrayList<Orderable> list = new ArrayList<Orderable>();
    Orderable j = new Food("족발", 19800);
    Orderable e = new Electronics("에어팟", 199000);
    Orderable c = new Clothing("셔츠", 49900);
    list.add(j);
    list.add(e);
    list.add(c);
    // 총합 계산
    int sum = 0;
    for (int i = 0; i < list.size(); i++){
      Orderable o = list.get(i);
      sum += o.discountedPrice();
    }
    // 결과 출력
    System.out.printf("총합: %d원", sum);
  }
}
interface Orderable {
  public int discountedPrice();
}
class Food implements Orderable {
  private String name;
  private int price;
  public Food(String name, int price) {
    this.name = name;
    this.price = price;
  }
  /* 1. 오버라이딩을 통해, 음식 할인율을 적용하세요. */
  public int discountedPrice(){
    return (int)(this.price*0.9);
  }
}
class Electronics implements Orderable {
  private String name;
  private int price;
  public Electronics(String name, int price) {
    this.name = name;
    this.price = price;
  }
  /* 2. 오버라이딩을 통해, 전자기기 할인율을 적용하세요. */
  public int discountedPrice(){
    return (int)(this.price*0.8);
  }
}
class Clothing implements Orderable {
  private String name;
  private int price;
  public Clothing(String name, int price) {
    this.name = name;
    this.price = price;
  }
  /* 3. 오버라이딩을 통해, 의류 할인율을 적용하세요. */
  public int discountedPrice(){
    return (int)(this.price*0.7);
  }
}

7) Review: interface

CODE

import java.util.ArrayList;
public class InterfaceReview {
  public static void main(String[] args) {
    // 객체 생성
    ArrayList<Sounding> list = new ArrayList<Sounding>();
    Sounding d = new Dog();
    Sounding b = new Baby();
    Sounding t = new Tiger();
    Sounding r = new Robot();
    // 인터페이스 배열 생성
    list.add(d);
    list.add(b);
    list.add(t);
    list.add(r);
    // 소리내기
    for (int i = 0; i < list.size(); i++){
      Sounding o = list.get(i);
      o.sound();
    } 
  }
}
/* 인터페이스 및 클래스를 작성하시오. */
interface Sounding{
  public void sound();
}
class Dog implements Sounding{
  public void sound(){
    System.out.println("Dog: 멍멍!");
  }
}
class Baby implements Sounding{
  public void sound(){
    System.out.println("Baby: 응애!");
  }
}
class Tiger implements Sounding{
  public void sound(){
    System.out.println("Tiger: 어흥!");
  }
}
class Robot implements Sounding{
  public void sound(){
    System.out.println("Robot: 삐빕!");
  }
}
profile
블로그 이전 : https://medium.com/@jaegeunsong97

0개의 댓글