ABCD

인터페이스 본문

PROGRAMMING LANGUAGE/JAVA

인터페이스

카메사마 2024. 6. 9. 15:44

🐢 인터페이스 장점
    - 인터페이스만 준수하면 통합에 신경쓰지 않고 다양한 형태로 새로운 클래스를 개발할 수 있다.
    - 클래스의 다중 상속을 지원하지 않지만, 인터페이스로 다중 상속 효과를 간접적으로 얻을 수 있다.
 
🐢 인터페이스와 추상 클래스 구별하기

분류 인터페이스 추상 클래스
구현 메서드 포함 불가
(단, 디폴트 메서드와 정적 메서드 예외)
포함 가능
인스턴스 변수 포함 불가 포함 가능
다중 상속 가능 불가능
디폴트 메서드 선언 가능 선언 불가능
생성자와 main() 선언 불가능
(클래스가 아니라 생성자가 없다.)
선언 가능
상속에서의 부모 인터페이스 인터페이스, 추상 클래스
접근 범위 모든 멤버를 공개 추상 메서드를 최소한 자식에게 공개

 
🐢 대표적인 인터페이스
    - java.lang 패키지의 CharSequence, Comparable, Runnable
    - java.util 패키지의 Collection, Comparator, List
 
🐢 인터페이스 구조

interface 인터페이스이름{
	// 상수 필드 --> 상수만 가능하기 때문에 public static final 키워드 생략 가능 (변수x)
    
    // public abstract 메서드
    // --> 인터페이스의 모든 메서드 (default, static, private 메서드 제외)가 public abstract이기 때문에 public abstract 키워드 생략 가능
    
    // default 메서드 --> 인터페이스에 메서드의 기본 구현을 제공하는데 사용 (오버라이딩 가능)
    
    // static 메서드 --> 구현 클래스에서 오버라이딩 불가
    
    // private 메서드 --> 인터페이스 내에서만 사용 가능
}

// 인터페이스 멤버에 명시된 public, static, final, abstract 키워드는 생략 가능하다.
// public: 모든 곳에서 접근 가능
// static: 클래스 수준에서 공유됨 (모든 객체들이 공유하는 변수)
// final: 한 번 할당된 후 변경 못한다.
// 생략한 키워드는 컴파일 과정에서 자동으로 추가된다.

 
🐢 default 메서드와 static 메서드
    - default 메서드는 오버라이딩 될 수 있지만, static 메서드는 오버라이딩 될 수 없다.
    - default 메서드는 인스턴스 메서드이므로 객체를 생성한 후 호출하지만, static 메서드는 인터페이스로 직접 호출한다.
    ! 정적 메서드는 객체를 생성하지 않기 때문에 인터페이스로 직접 호출하여 오버라이딩이 불가하다.
 
🐢 인터페이스를 쓰는 이유
    하위에 수많은 클래스들에다 만들고 싶은 메서드들을 이미 인터페이스에 정리해두었다.
    --> 인터페이스에 명시되어 있는 것을 바탕으로 기본적 구현을 하면 된다.
    ! 클래스가 객체를 만들기 위한 도안이라면 인터페이스는 세부적인 클래스를 만들기 위한 도안이다.
 
🐢 default 메서드 --> 인터페이스 수정과 기존 구현 클래스
    - 인터페이스에 메서드를 추가하면 해당 인터페이스를 구현하는 모든 클래스들이 그 메서드를 구현해야 함
    ! 기존 코드의 안정성을 해칠 수 있다. (ex) 기존의 모든 코드들이 새로운 메서드를 구현하도록 수정하기)
    --> default 키워드를 사용하여 인터페이스에 새로운 메서드를 추가하면서 기본 구현을 제공할 수 있다.

// 메서드 정의 시
default 반환타입 디폴트메서드이름(){}

 
🐢 인터페이스 상속

// 인터페이스 상속 시 extends 키워드 사용
interface 자신인터페이스 extends 부모인터페이스{}

// 인터페이스 구현 시 implements 키워드를 사용
class 자식클래스 implements 부모인터페이스{}

 
🐢 클래스와 인터페이스의 관계
    - class extends class
    - interface extends interface
    - class implements interface
 
! 불가능
    - interface extends class
    - interface implements class
 
🐢 인터페이스를 이용한 다중 상속 효과
    - interface extends interface, interface
    --> 여러 개의 interface 상속받을 수 있다.
    - class implements interface, interface
    --> 인터페이스 여러 개를 구현할 수 있다.
    - class extends class implements interface
    --> 구현: 인터페이스에 정의되어 있는 메서드를 오버라이딩해서 사용한다. 기본 클래스가 인터페이스에 제공되어 있으면 오버라이딩 하지 않아도 사용이 가능하다.

    ! 불가능
        - class extends class, class
    클래스는 다중 상속 할 수 없다.
 
🐢 인터페이스 타입
    - 인터페이스도 클래스처럼 하나의 타입이므로 변수를 인터페이스 타입으로 선언 가능하다.
    - 인터페이스의 구현 클래스는 그 인터페이스의 자식 타입이다.
    - 인터페이스 타입 변수가 구현 객체를 참조한다면 강제 타입 변환이 가능하다.
 
🐢 중첩 클래스: 클래스 안에 또 다른 클래스가 정의되는 것이다.
    --> 특정 클래스를 자신의 클래스 내부적으로만 사용하고 싶을 때 사용한다.
    - 중첩 클래스는 외부 클래스를 상속할 필요없이 외부 클래스의 private 멤버까지 사용할 수 있다.
 
🐢 중첩 클래스 종류
    - 멤버 클래스
        - 정적 멤버 클래스
        - 내부 클래스 (인스턴스 멤버 클래스)
    - 지역 클래스

// 중첩 클래스의 구조
class 외부클래스{
	class 멤버클래스{}  			// 외부 클래스의 멤버로 선언된 클래스 
    interface 중첩인터페이스{}
}

class 외부클래스{
	void 메서드(){
    	class 지역클래스{}		// 외부 클래스의 메서드 내부에 선언된 클래스
    }
}

// 컴파일 후 생성파일
// 외부클래스$멤버클래스.class
// 외부클래스$중첩인터페이스.class
// 외부클래스$1지역클래스.class			// 이름이 동일한 지역 클래스가 있다면 $2, $3 ...

 

// 외부 클래스 접근 시
외부클래스.this

// 중첩 클래스의 객체 생성
외부클래스.내부클래스 변수=외부클래스의객체변수.new 내부클래스생성자();
외부클래스.정적멤버클래스 변수=new 외부클래스.정적멤버클래스생성자();

 
🐢 자바 라이브러리: 개발자가 편리하게 사용할 수 있도록 패키지 혹은 모듈을 묶은 파일
    JDK(Java Development Kit): 개발을 편리하게 할 수 있도록 다양한 것을 미리 제공해준다.
    - 패키지: 상호 관련있는 클래스와 인터페이스를 묶은 것
    - 모듈: 밀접한 관계가 있는 패키지와 리소스를 묶은 것


// 예시1

package main;

interface Coin {
	int PENNY = 1, NICKEL = 5, DIME = 10, QUARTER = 25;
}

public class Main {
	public static void main(String[] args) {
		System.out.println("Dime은 " + Coin.DIME + "센트입니다.");
	}
}

/*
public class Main implements Coin {
	public static void main(String[] args) {

		System.out.println("Dime은 " + DIME + "센트입니다.");

	}
}
*/
// 예시2

package main;

interface Movable {
	void move(int x);
}

class Car implements Movable {
	private int pos = 0;

	public void move(int x) {
		pos += x;
	}

	public void show() {
		System.out.println(pos + "m 이동했습니다.");
	}
}

public class Main {
	public static void main(String[] args) {
		Movable m = new Car();

		m.move(5);
		// m.show();

		Car c = (Car) m;
		c.move(10);
		c.show();
	}
}
// 예시3

package main;

public class Main {
	private String secret = "비공개";
	String s = "외부";

	class MemberClass {
		String s = "내부";

		public void show1() {
			System.out.println("내부 클래스");
			System.out.println(secret);

			System.out.println(s);

			System.out.println(Main.this.s);
		}


	}

	public static void main(String[] args) {
		Main m = new Main();
		Main.MemberClass m1 = m.new MemberClass();

		System.out.println(m1.s);
		m1.show1();
	}
}
// 예시4

package main;

class Mouse {
	String name;

	public Mouse(String name) {
		this.name = name;
	}
}

class Keyboard {
	String name;

	public Keyboard(String name) {
		this.name = name;
	}

	public boolean equals(Object obj) {
		if (obj instanceof Keyboard) {
			Keyboard k = (Keyboard) obj;
			if (name.equals(k.name))
				return true;
		}
		return false;
	}

	public String toString() {
		return "키보드입니다.";
	}
}

public class Main {
	public static void main(String[] args) {
		Mouse m1 = new Mouse("Logitech");
		Mouse m2 = new Mouse("Logitech");
		Mouse m3 = m1;
		Keyboard k1 = new Keyboard("Microsoft");
		Keyboard k2 = new Keyboard("Microsoft");

		System.out.println(m1.toString());
		System.out.println(m1);

		System.out.println(k1.toString());
		System.out.println(k1);

		System.out.println(m1.equals(m2));
		System.out.println(m1.equals(m3));
		System.out.println(k1.equals(k2));
	}
}
// 예시5

package main;

class Keyboard {
	String name;

	public Keyboard(String name) {
		this.name = name;
	}

	public boolean equals(Object obj) {
		if (obj instanceof Keyboard) {
			Keyboard k = (Keyboard) obj;
			if (name.equals(k.name))
				return true;
		}
		return false;
	}

	public String toString() {
		return "키보드입니다.";
	}
}

public class Main{
	public static void main(String[] args) {
		Keyboard k = new Keyboard("Logitech");

		Class c = k.getClass();
		System.out.println(c.getName());
		System.out.println(c.getSimpleName());
		System.out.println(c.getTypeName());
	}
}
// 예시6

package main;

public class Main {
	public static void main(String[] args) {
		System.out.println("Math.pow(2, 8) : " + Math.pow(2, 8));

		System.out.println("Math.random() : " + Math.random());

		System.out.println("Math.sin(Math.PI) : " + Math.sin(Math.PI));

		System.out.println("Math.min(10, 20) : " + Math.min(10, 20));
	}
}
// 예시7

package main;

public class Main {
	public static void main(String[] args) {
		int[] src = new int[] { 1, 2, 3, 4, 5, 6 };
		int[] dst = { 100, 200, 300, 400, 500, 600, 700 };
		
		System.arraycopy(src, 2, dst, 3, 4);
		for (int i = 0; i < dst.length; i++) {
			System.out.print(dst[i] + " ");
		}
		System.out.println();

		System.out.println(System.currentTimeMillis());
		System.out.println(System.getenv("JAVA_HOME"));
		System.out.println(System.getProperty("os.name"));
		System.out.println(System.nanoTime());
	}
}
// 예시8

package main;

import java.util.Random;

public class Main {
	public static void main(String[] args) {
		Random r = new Random();

		for (int i = 0; i < 5; i++)
			System.out.print(r.nextInt(100) + " ");
	}
}

'PROGRAMMING LANGUAGE > JAVA' 카테고리의 다른 글

패키지와 API 문서  (0) 2024.09.07
열거 타입  (0) 2024.06.10
예외처리  (0) 2024.06.09
상속과 추상 클래스  (0) 2024.06.09