220609~0611_인터넷 강의_인터페이스

창고·2022년 10월 20일
0

티스토리에 저장했던 글을 옮겼습니다.
https://mrcocoball.tistory.com/82
https://mrcocoball.tistory.com/83

1. 인터페이스 (interface)

(1) 인터페이스란?

  • 모든 메소드가 추상 메소드로 선언됨 public abstract (별도로 지정하지 않아도 컴파일 과정에서 자동으로 됨)
  • 모든 변수는 상수로 선언됨 public static final (별도로 지정하지 않아도 컴파일 과정에서 자동으로 됨)
interface 인터페이스 이름{

   public static final float pi = 3.14F;
   public void makeSomething();
}
  • Java 8부터 디폴트 메소드와 정적 메소드 기능의 제공으로 일부 구현 코드가 있음

(2) 인터페이스 정의와 구현

  • Calc ← Calculator ← CompleteCalc
  • [Calc.java]
public interface Calc {
	
	   double PI = 3.14; // 상수 필드 선언
	   int ERROR = -99999999; // 상수 필드 선언
	   
	   // 추상 메소드
	   int add(int num1, int num2);
	   int substract(int num1, int num2);
	   int time(int num1, int num2);
	   int divide(int num1, int num2);

}
  • [Calculator.java]
//추상 클래스, Calc를 implement
public abstract class Calculator implements Calc {
	
	   @Override // 추상 메소드 재정의하여 구체화
	   public int add(int num1, int num2) {
	      return num1 + num2;
	   }

	   @Override // 추상 메소드 재정의하여 구체화
	   public int substract(int num1, int num2) {
	      return num1 - num2;
	   }

}
  • [CompleteCalc.java]
public class CompleteCalc extends Calculator { // Calculator를 상속
	
	   @Override // 추상 메소드 재정의하여 구체화
	   public int time(int num1, int num2) {
	      return num1 * num2;
	   }

	   @Override // 추상 메소드 재정의하여 구체화
	   public int divide(int num1, int num2) {
	      if (num2 == 0)
	         return ERROR;   
	      else
	         return num1 / num2;
	   }

	   public void showInfo() {
	      System.out.println("모두 구현 완료");
	   }

}
  • [CalculatorTest.java]
public class CalculatorTest {

	public static void main(String[] args) {
		Calc calc = new CompleteCalc(); // 인터페이스를 구현한 클래스는 인터페이스 형으로 선언한 변수로 형변환 가능
		int num1 = 10;
		int num2 = 2;

		System.out.println(num1 + "+" + num2 + "=" + calc.add(num1, num2));
		System.out.println(num1 + "-" + num2 + "=" + calc.substract(num1, num2));
		System.out.println(num1 + "*" + num2 + "=" + calc.time(num1, num2));
		System.out.println(num1 + "/" + num2 + "=" + calc.divide(num1, num2));

	}
}

(3) 인터페이스 구현과 형 변환

  • 인터페이스를 구현한 클래스는 인터페이스 형으로 선언한 변수로 형 변환 할 수 있음 (업 캐스팅과 동일)
Calc calc = new CompleteCalc();
  • 클래스 상속과 달리 구현 코드가 없어 여러 인터페이스를 구현할 수 있음
Calculator implements Calc, Calc2, Calc3 ...
  • 형 변환되는 경우에는 인터페이스에 선언된 메서드만 사용 가능

(4) 인터페이스의 기능, 사용 목적

  • 클래스나 프로그램이 제공하는 기능을 명시적으로 선언
  • 일종의 클라이언트 코드와의 약속, 클래스나 프로그램이 제공하는 명세(spectification)
  • 클라이언트 프로그램은 인터페이스에 선언된 메소드 명세만 보고 이를 구현한 클래스를 사용할 수 있음
  • 어떤 객체가 하나의 인터페이스 타입이라는 것은 그 인터페이스가 제공하는 모든 메소드를 구현했다는 의미
  • 인터페이스를 구현한 다양한 객체를 사용 -> 다형성

2. 인터페이스의 여러가지 요소

public interface Calc {
	
	   double PI = 3.14; // 상수 필드 선언
	   int ERROR = -99999999; // 상수 필드 선언
	   
	   // 추상 메소드
	   int add(int num1, int num2);
	   int substract(int num1, int num2);
	   int time(int num1, int num2);
	   int divide(int num1, int num2);
	   
	   default void description() {
		   System.out.println("정수의 사칙연산을 제공합니다.");
		   myMethod(); // 재정의 불가
	   }
	   
	   static int total(int[] arr) { // 배열을 받아서 배열 내부 저장
		   
		   int total = 0;
		   for (int num : arr) {
			   total += num;
			   
		   }
		   myStaticMethod(); // 재정의 불가
		   return total;
		   
	   }
	   
	   private void myMethod() {
		   System.out.println("myMethod");
	   }
	   
	   private static void myStaticMethod() {
		   System.out.println("myStaticMethod");
	   }

}

(1) 상수

  • 모든 변수는 상수로 변환되며 기재를 하지 않아도 컴파일러를 거쳐 자동적으로 public static final이 됨

(2) 추상 메소드

  • 모든 선언 메소드는 추상 메소드가 되며 기재를 하지 않아도 컴파일러를 거쳐 자동적으로 public abstarct가 됨

(3) 디폴트 메소드 (default)

  • 구현을 가지는 메소드이며 인터페이스를 구현하는 클래스들에서 공통으로 사용할 수 있는 기본 메소드
  • 구현하는 클래스에서 재정의할 수 있음

(4) 정적 메소드 (static)

  • 인스턴스 생성과 상관 없이 인터페이스 타입으로 사용할 수 있는 메소드
Calc.정적 메소드로 인스턴스 생성 없이 바로 Calc의 정적 메소드를 호출하는 코드
		int[] arr = {1,2,3,4,5};
		Calc.total(arr); // 정적 메소드, 구현 클래스 인스턴스 생성 없이도 가능, 인터페이스 이름.정적 메소드로 호출
		System.out.println(Calc.total(arr));

(5) private 메소드

  • 인터페이스를 구현한 클래스에서 사용 / 재정의 불가
  • 인터페이스 내부에서만 사용하는 메소드
  • default나 static 메소드에서 사용

3. 인터페이스의 상속

(1) 여러 인터페이스의 구현

  • 자바의 인터페이스는 구현 코드가 없어 하나의 클래스가 여러 인터페이스를 구현할 수 있음
  • 다만, 디폴트 메소드가 중복되는 경우에는 구현 하는 클래스에서 재정의가 필요
  • 여러 인터페이스를 구현한 클래스는 인터페이스 타입으로 형변환 될 경우 해당 인터페이스에 선언된 메소드만 사용 가능
  • Buy
public interface Buy {
	
	void buy();
	
	default void order() {
		System.out.println("buy order");
	}

}
  • Sell
public interface Sell {
	
	void sell();
	
	default void order( ) {
		System.out.println("sell order");
	}

}
  • Customer
public class Customer implements Buy, Sell {
	
	@Override
	public void sell() {
		
		System.out.println("판매합니다");
	}
	
	@Override
	public void buy() {
		
		System.out.println("구매합니다");
	}	
	
	@Override
	public void order() {
		
		System.out.println("주문합니다");
	}	
	
	public void hello() {
		System.out.println("안녕");
	}

}
  • CustomerTest
public class CustomerTest {

	public static void main(String[] args) {
		Customer customer = new Customer();
		customer.buy();
		customer.sell();
		customer.order();
		customer.hello();
		
		Buy buyer = customer;
		buyer.buy();
		buyer.order(); // Customer에서 재정의했으므로 Buy의 order 호출 안됨
		
		Sell seller = customer;
		seller.sell();
		seller.order(); // Customer에서 재정의했으므로 Sell의 order 호출 안됨

	}

}

(2) 인터페이스의 상속

  • 인터페이스 사이에도 상속이 가능하며 extends 키워드를 사용
  • 인터페이스는 다중 상속이 가능하고 구현 코드의 상속이 아니므로 타입 상속이라고 함

(3) 클래스 상속과 인터페이스 구현 함께 사용하기

  • 실무에서 프레임워크나 오픈소스와 함께 연동되는 구현을 하게 되면 클래스 상속과 인터페이스의 구현을 같이 사용하는 경우가 많음
  • 예제
    • BookShelf는 Shelf 클래스를 extends 하고 Queue 인터페이스를 implements함
    • 책을 보관하는 자료 구조가 Shelf에 구현됨 (ArrayList)
    • 책이 순서대로 대여가 됨
  • Shelf
public class Shelf {
	
	protected ArrayList<String> shelf; // ArrayList 타입의 변수 shelf
	
	public Shelf() {
		shelf = new ArrayList<String>(); // shelf 라는 이름으로 ArrayList 생성
	}
	
	public ArrayList<String> getShelf() { // getShelf() 로 ArrayList 타입의 shelf 리턴
		return shelf;
	}

	public int getCount() {
		return shelf.size(); // shelf의 길이를 리턴
	}
}
  • Queue
public interface Queue {
	
	void enQueue(String title); // 책 이름 title을 적어서 책을 보관
	String deQueue(); // 책의 이름 String 타입으로 꺼냄
	
	int getSize();

}
  • BookShelf
public class BookShelf extends Shelf implements Queue {

	@Override
	public void enQueue(String title) {
		shelf.add(title); // title을 받아서 책을 저장
		
	}

	@Override
	public String deQueue() {
		return shelf.remove(0); // 맨 첫번째 책을 지우면서 책 이름을 반환
	}

	@Override
	public int getSize() {
		return getCount();
	}
}
  • 실행
public class BookShelfTest {

	public static void main(String[] args) {
		Queue bookQueue = new BookShelf(); // 인터페이스 타입으로 BookShelf 형 변환
		bookQueue.enQueue("러브라이브1");
		bookQueue.enQueue("러브라이브2");
		bookQueue.enQueue("러브라이브3");
		bookQueue.enQueue("러브라이브4");
		bookQueue.enQueue("러브라이브5");
		
		System.out.println(bookQueue.getSize());
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.deQueue());

	}

}

profile
공부했던 내용들을 모아둔 창고입니다.

0개의 댓글