유쨈미 2024. 4. 13. 15:14

1. Interface

자바에서 Interface는 클래스가 구현해야 할 메소드의 템플릿을 제공한다. Interface는 메소드의 시그니처만을 정의하며, 실제 메소드의 구현은 인터페이스를 구현(implements)하는 클래스에서 이루어진다. Interface는 자바의 다형성을 지원하는 중요한 수단으로 클래스가 여러 인터페이스를 구현할 수 있기 때문에 다중상속과

유사한 효과를 낼 수 있다.

 

💡 JAVA Interface

  1. 정의
    메소드의 시그니처만 정의하며, 구현은 하지 않는다.
  2. 목적
    다형성을 지원하고, 다중 상속의 문제를 피하면서 클래스에 여러 행동을 강제할 수 있다.
  3. 사용
    implements 키워드를 사용하여 인터페이스를 구현한다.

 

💻 예시 코드

package pack03;

//	1. 추상 메소드와 상수로 구성된 클래스
//	2. 다중상속이 가능
//	3. 인터페이스는 인스턴스(new) 할 수 없다.
//	4. 인터페이스는 자식 클래스에서 implementd 키워드로 구현한다.
//	5. 인터페이스간 상속이 가능

public interface Ex20_Volume {
	void volumeUp(int level);

	void volumeDown(int level);
}
//	void print();
// 일반 메소드는 사용할 수 없다.
package pack03;

public class Ex20_Radio implements Ex20_Volume {
	private int volLevel;
	
	public Ex20_Radio() {	// 라디오 생성자
		volLevel = 0;
	}
	@Override
	public void volumeUp(int level) {
		volLevel += level;
		System.out.println("라디오 볼륨을 올리면 " + volLevel);
	}

	@Override
	public void volumeDown(int level) {
		volLevel -= level;
		System.out.println("라디오 볼륨을 내리면 " + volLevel);
	}
	
}
package pack03;

public class Ex20_Tv implements Ex20_Volume {
	private int volLevel;
	
	public Ex20_Tv() {	// Tv 생성자
		volLevel = 0;
	}

	@Override
	public void volumeUp(int level) {
		volLevel += level;
		System.out.println("Tv 볼륨을 올리기 " + volLevel);
		String msg = "Tv 볼륨을 높이기";
	}
	
	@Override
	public void volumeDown(int level) {
		volLevel -= level;
		String msg = "Tv 볼륨을 내리기 ";
		System.out.println(msg + volLevel);
	}
	
}
package pack03;

public class Ex20_HandPhone implements Ex20_Volume {
	private int volLevel;
	
	public Ex20_HandPhone() {	// 핸드폰 생성자
		volLevel = 0;
	}
	@Override
	public void volumeUp(int level) {
		// 인터페이스의 추상메소드를 오버라이딩
		if(level > 100) level = 100;
		volLevel += level;
		System.out.println("핸드폰 소리를 올리면 "+ volLevel);
	}
	@Override
	public void volumeDown(int level) {
		volLevel -= level;
		if(volLevel < 0) volLevel = 0;
		System.out.println("핸드폰 소리를 내리면 "+ volLevel);
	}
	
	
}
package pack03;

public class Ex20_Main {

	public static void main(String[] args) {
//		Ex20_Volume volume = new Ex20_Volume();	// x
		Ex20_Volume volume;	// o
		
		Ex20_Radio radio = new Ex20_Radio();
		Ex20_Tv tv = new Ex20_Tv();
		Ex20_HandPhone phone = new Ex20_HandPhone();
		
		radio.volumeUp(5);
		radio.volumeDown(2);
		tv.volumeUp(10);
		tv.volumeDown(7);
		phone.volumeUp(7);
		phone.volumeDown(1);
		
		System.out.println("-----------");
		volume = radio;
		volume.volumeUp(1);
		volume = tv;
		volume.volumeUp(2);
		volume = phone;
		volume.volumeUp(3);
		
		System.out.println("-----------");
		Ex20_Volume volArr[] = new Ex20_Volume[3];	// 3개짜리 배열 만듦.
		volArr[0] = radio;
		volArr[1] = tv;
		volArr[2] = phone;
		
		System.out.println("\n---- 배열 for문 ----");
		for(int a = 0; a < volArr.length; a++) {
			volArr[a].volumeDown(1);
		}
		
		System.out.println("\n---- 향상된 for문 ----");
		for(Ex20_Volume mbc:volArr) {	// 향상된 for문
			mbc.volumeDown(1);
		}
		
	}

}

💻 결과

라디오 볼륨을 올리면 5
라디오 볼륨을 내리면 3
Tv 볼륨을 올리기 10
Tv 볼륨을 내리기 3
핸드폰 소리를 올리면 7
핸드폰 소리를 내리면 6
-----------
라디오 볼륨을 올리면 4
Tv 볼륨을 올리기 5
핸드폰 소리를 올리면 9
-----------

---- 배열 for문 ----
라디오 볼륨을 내리면 3
Tv 볼륨을 내리기 4
핸드폰 소리를 내리면 8

---- 향상된 for문 ----
라디오 볼륨을 내리면 2
Tv 볼륨을 내리기 3
핸드폰 소리를 내리면 7

2. Interface 다중상속

💻 예제 코드

package pack03;

//public interface Ex22_InterVol {

//인터페이스간 상속(extends)도 가능함
public interface Ex22_InterVol extends Ex22_VolEtc {
	String vol = "볼륨";
	
	void volUp(int v);
	void volDown(int v);
}
package pack03;

public interface Ex22_VolEtc {
	void volOff();
	void volOn();
}
package pack03;

// 인터페이스는 implements를 통해 다중상속의 효과를 볼 수 있다. (콤마(,)로 클래스 구분)
public class Ex22_Radio implements Ex22_InterVol {
	private int v = 0;
	
	@Override
	public void volUp(int v) {
		this.v += v;
	}
	@Override
	public void volDown(int v) {
		this.v -= v;
	}
	
	@Override
	public void volOff() {
		v = 0;
	}
	
	@Override
	public void volOn() {
		v = 1;
	}
	
	public void showVol() {
		System.out.println("현재 볼륨은 " + v);
	}
}
package pack03;

public class Ex22_Main {

	public static void main(String[] args) {
		Ex22_Radio radio = new Ex22_Radio();
		radio.volOn();
		radio.volUp(5);
		radio.volDown(2);
		radio.showVol();
		radio.volOff();
		radio.showVol();
	}
}

💻 결과

현재 볼륨은 4
현재 볼륨은 0

3. Window Listener

자바에서 Window Listener는 AWT(Abstract Winodw Tookit)에서 창 이벤트를 처리하기 위한 인터페이스이다.

이 인터페이스는 창이 열리거나 닫히는 등의 사용자 인터렉션을 감지하는 메소드를 제공한다. 

 

💡 Window Listener 메소드

  1. windowOpened(WindowEvent e)
    창이 열릴 때 호출된다.
  2. windowClosing(WindowEvent e)
    창을 닫으려고 할 때 호출된다.
  3. windowClosed(WindowEvent e)
    창이 닫힌 후 호출된다.
  4. windowIconified(WindowEvent e)
    창이 아이콘 상태로 최소화될 때 호출된다.
  5. windowDeiconified(WindowEvent e)
    창이 아이콘 상태에서 복원될 때 호출된다.
  6. windowActivated(WindowEvent e)
    창이 활성화될 때 호출된다.
  7. windowDeactivated(WindowEvent e)
    창이 비활성화될 때 호출된다.

 

💻 예제 코드

package pack03;

import java.awt.Color;
import java.awt.Frame;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

// 인터페이스를 이용한 이벤트 처리 연습
public class MyFrame03 extends Frame implements WindowListener, MouseListener {
	public MyFrame03() {
		// 생성자
		super("상속 사용");
		super.setTitle("상속 사용");
		
		display();
		
		// 현재 Frame에 이벤트 리스너를 장착
		super.addWindowListener(this);	// 아규먼트 값에 this를 쓰면 MyFrame03을 가리킨다.
		addMouseListener(this);
	}
	
	void display() {
		setSize(500, 300);
		setLocation(700, 450);
		setVisible(true);
	}
	
	// WindowListener가 가진 추상메소드 오버라이딩
	@Override
	public void windowActivated(WindowEvent e) {
	}

	@Override
	public void windowClosed(WindowEvent e) {
	}
	
	@Override
	public void windowClosing(WindowEvent e) {
		System.exit(0);		// << 탈출구
		
	}
	
	// 창 이벤트
	@Override
	public void windowDeactivated(WindowEvent e) {
	}

	@Override
	public void windowDeiconified(WindowEvent e) {	// 창 열기 할 때 반응
		System.out.println("windowDeiconified");
	}

	@Override
	public void windowIconified(WindowEvent e) {	// 창 닫기 할 때 반응
		System.out.println("windowIconified");
	}
	
	@Override
	public void windowOpened(WindowEvent e) {
		System.out.println("windowOpened");
	}
	
	// 마우스 이벤트
	@Override
	public void mouseClicked(MouseEvent e) {
		int r = (int)(Math.random() * 255);
		int g = (int)(Math.random() * 255);
		int b = (int)(Math.random() * 255);
		setBackground(new Color(r, g, b));
	}
	@Override
	public void mouseEntered(MouseEvent e) {
		
	}
	@Override
	public void mouseExited(MouseEvent e) {
		
	}
	@Override
	public void mousePressed(MouseEvent e) {
		
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		
	}
	
	public static void main(String[] args) {
		new MyFrame03();
	}
}

💻 결과

닫기 버튼 누르면 꺼진다!

 

[Web] 리스너(Listener)

리스너 리스너(Listener)란 컨테이너에서 발생하는 이벤트를 모니터링하다가 특정 이벤트가 발생하면 실행되는 특수한 서블릿으로, '이벤트 리스너(Event Listener)'라고도 한다. 웹 애플리케이션 실

arajo.tistory.com

- 출처 : arajo tistory

 

Java - extends, implements, abstract 차이

상속이라는 개념을 이론적으로 분명 학습했는데, 잘 안쓰다보니(직접 만들어 쓴적은 없다는 얘기... JpaRepository 인터페이스 같은 것은 자주 사용...) 그 개념을 자꾸 잊어먹어서 implements, extends 심

rok93.tistory.com

- 출처 : rok93 tistory


4. Adapter

일반적으로 인터페이스를 구현하는데 필요한 작업을 간소화하는 데 사용되는 디자인 패턴이다.

특히, 이 패턴은 Event Listener와 같은 여러 메소드를 가진 인터페이스에서 유용하게 사용된다.

자바에서는 인터페이스의 모든 메소드를 구현해야 하는 부담을 줄이기 위해 Adapter Class를 제공한다.

이러한 Adapter Class는 Interface의 모든 메소드를 빈 구현으로 제공하여, 개발자가 필요한 메소드만
오버라이드
할 수 있게 한다.

 

💡 Adapter 패턴의 장점

  1. 코드 간결성
    필요 없는 메소드 구현을 생략할 수 있어 코드가 간결해진다.
  2. 유연성
    특정 메소드에 대한 구현을 제공하면서 나머지는 기본 동작을 유지할 수 있다.
  3. 재사용성
    같은 Adapter Class를 다양한 컴포넌트에서 재사용할 수 있다.

Adapter 패턴은 코드를 효율적으로 관리하고, Interface를 더 유연하게 구현할 수 있도록 도와주는
중요한 패턴 중 하나이다.

 

💻 예제 코드

package pack03;

// 날아 다니는 것에 관련된 멤버를 정의한 인터페이스
public interface Ex23_Flyer {
	int FAST = 100;
	
	void fly();
	boolean isAnimal();
	void happy();
}
package pack03;

public class Ex23_Bird implements Ex23_Flyer {
	@Override
	public void fly() {
		System.out.println("날개를 휘 저으며 숲으로 날아감");
	}
	@Override
	public boolean isAnimal() {
		return true;
	}
	@Override
	public void happy() {
		
	}
}
package pack03;

public class Ex23_AirPlane implements Ex23_Flyer {
	@Override
	public void fly() {
		System.out.println("커다란 엔진 소리를 내며 인천공항을 이륙함");
	}
	@Override
	public boolean isAnimal() {
		return false;
	}
	@Override
	public void happy() {
		
	}
}
package pack03;

public class Ex23_Main {

	public static void main(String[] args) {
		System.out.println("속도 : " + Ex23_Flyer.FAST);
		
		Ex23_Bird bird = new Ex23_Bird();
		bird.fly();
		
		Ex23_AirPlane airplane = new Ex23_AirPlane();
		airplane.fly();
		
		System.out.println();
		Ex23_FlyerUtill.show(bird);		// 주소 치환중...
		System.out.println();
		Ex23_FlyerUtill.show(airplane);
		
		System.out.println();
		Ex23_Ball ball = new Ex23_Ball();
		ball.fly();
	}

}

5.  Adapter Class

package pack03;

public class Ex23_FlyerUtill {
	public static void show(Ex23_Flyer f) {
		f.fly();
		System.out.println("동물인가요? :3  //" + f.isAnimal());
		
	}
}
package pack03;

// Adapter란 이름이 붙은 클래스는 인터페이스를 구현해 추상을 일반 메소드로 작성
// 그리고 자신은 추상클래스가 된다.
abstract class Ex23_FlyerAdapter implements Ex23_Flyer {
	@Override
	public void fly() {}
	
	@Override
	public boolean isAnimal() {return false;}
	
	@Override
	public void happy() {}
}
package pack03;

// 인터페이스를 구현하고 모든 추상 메소드를 오버라이드 하는 지옥에서 벗어날 수 있땅.
// 추상을 일반 메소드로 만들어 둔 어댑터 클래스를 상속받아 선택적으로 메소드를 작성.
// public class Ex23_Ball implements Ex23_FlyerAdapter{
public class Ex23_Ball extends Ex23_FlyerAdapter{
	@Override
	public void fly() {
		System.out.println("공이 관중석으로 날아감");
	}
}

💻 결과

속도 : 100
날개를 휘 저으며 숲으로 날아감
커다란 엔진 소리를 내며 인천공항을 이륙함

날개를 휘 저으며 숲으로 날아감
동물인가요? :3  //true

커다란 엔진 소리를 내며 인천공항을 이륙함
동물인가요? :3  //false

공이 관중석으로 날아감
 

[JAVA / 디자인 패턴] 어댑터 패턴 ( Adapter Pattern )

어댑터란 무엇일까? 물리적인 의미로 이야기 하자면, 다른 전기나 기계 장치를 서로 연결해서 작동할 수 있도록 만들어주는 결합 도구이다. 예시로 이야기 하자. 충전 단자 부분이 USB 형식인 애

wooni1849.tistory.com

- 출처 : wooni1849 tistory


6. Inner Class (내부클래스)

내부 클래스는 다른 클래스 내부에 정의된 클래스로, 주로 외부 클래스와 긴밀하게 연관된 작업을 처리하기

위해 사용된다. 내부 클래스는 자신을 둘러싼 외부 클래스의 멤버에 접근할 수 있는 특별한 권한을 갖는다.

내부 클래스는 주로 이벤트 처리나 백그라운드 작업 처리에 사용되며, GUI 애플리케이션에 특히 유용하다.

 

💡 추가 설명

  1. 클래스 멤버로 전역변수 필드와 메소드, 클래스를 사용할 수 있다.
  2. 추가적으로 특정 클래스 내에서 클래스를 선언해서 사용할 수 있는데 이를 내부 클래스라고 한다.
  3. 내부 클래스는 독립적으로 인스턴스 할 수 없다. 내부 클래스를 포함한 외부 클래스에 의해 통제된다.

 

💻 예제 코드

package pack03;

import java.awt.event.WindowAdapter;

import javax.sound.sampled.SourceDataLine;

// 내부 클래스
// 클래스 멤버로 전역변수 필드와 메소드, 클래스를 사용할 수 있다.
// 추가적으로 특정 클래스 내에서 클래스를 선언해서 사용할 수 있는데 이를 내부 클래스라고 한다.
// 내부 클래스는 독립적으로 인스턴스 할 수 없다. 내부 클래스를 포함한 외부 클래스에 의해 통제된다.
public class Ex24_Outer {
	private int a;
	private Inner inner;
	
	public Ex24_Outer() {
		System.out.println("Outer 생성자");
		a = 10;
		inner = new Inner();	// 내부 클래스는 외부 클래스를 통해 인스턴스 한다.
	}
	
	public void aa() {
		System.out.println("외부에 있는 aa 메소드 실행");
		bb();			// aa와 동급
		inner.cc();		// cc메소드는 내부 클래스의 멤버
		System.out.println("1. Outer의 a: " + a + ", Inner의 b: " + inner.b);
	}
	
	public void bb() {
		System.out.println("외부에 있는 bb 메소드 처리");
	}
	
	public class Inner {		// 내부 클래스. Outer의 멤버
		private int b;
		
		public Inner() {
			System.out.println("Inner 생성자");
			b = 20;
		}
		public void cc() {
			System.out.println("내부 클래스에 있는 cc 메소드 처리");
			bb();		// 내부 클래스는 외부 클래스의 멤버를 자유롭게 호출 가능.
			System.out.println("2. Outer의 a: " + a + ", Inner의 b: " + inner.b);	// 알아서 외부로 찾아감. to aa();
		}
		
		public class InnerInner {  // 내부 클래스 내에서 다시 내부 클래스를 선언 가능. (계속 가능함.)
		}
	}
	
	// 내부 클래스의 수 만큼 extends를 사용할 수 있다.
	// public class Inner2 extends Frame {
		
     // }
	
	public class Inner3 extends WindowAdapter {
		
	}
}
package pack03;

import java.io.BufferedOutputStream;

public class Ex24_Main {

	public static void main(String[] args) {
		// 내부 클래스 연습용
		Ex24_Outer outer = new Ex24_Outer();
		outer.aa();
		outer.bb();
		// outer.cc();
		
		System.out.println();
		// Inner inner = new Inner();	// 내부 클래스는 독립적인 인스턴스 불가
		
		// 아래의 소스는 수행은 가능하나 현실적으로 사용하지 않는다.
		// Ex24_Outer.Inner inner = outer.new Inner();
		// inner.cc();
		
		System.out.println();
		outer.aa();
	}

}

💻 결과

Outer 생성자
Inner 생성자
외부에 있는 aa 메소드 실행
외부에 있는 bb 메소드 처리
내부 클래스에 있는 cc 메소드 처리
외부에 있는 bb 메소드 처리
2. Outer의 a: 10, Inner의 b: 20
1. Outer의 a: 10, Inner의 b: 20
외부에 있는 bb 메소드 처리


외부에 있는 aa 메소드 실행
외부에 있는 bb 메소드 처리
내부 클래스에 있는 cc 메소드 처리
외부에 있는 bb 메소드 처리
2. Outer의 a: 10, Inner의 b: 20
1. Outer의 a: 10, Inner의 b: 20

 

오늘은 오전 8시에 국취제 초기 상담 일정이 있어서 다녀왔는데 생각보다 너무 오래 걸려서(상담 + 이동시간)

수업에 30분 정도 늦게 들어갔다. 다행인지 아닌지 진도는 그렇게 많이 나가지 못했다. 다만 내가 없던 사이 Interface와 Implements에 대해서 듣지 못했기 때문에 무슨 말인지 처음에는 엄청 헷갈렸다.

컨디션 난조로 힘들기도 하고 멍도 엄청 때렸던 것 같다. 평소 안 하던 실수도 하고 아... 왜 이러지 하고 시무룩했었다가 오후에 어제 못한 코드설명을 함과 동시에 뿌듯함이 몰려왔다.

당연히 코드 설명을 완벽히 하지는 못했다. 내가 헷갈려하는 것과 내가 말하려고 하는 게 어떤 건지 강사님이

콕 찝어서 알려주셔서 코드 흐름을 파악하는데 도움이 엄청 많이 되었다. 그러다 보니 자연스럽게 Intreface에도 이해가 안 갔던 부분이 조금씩 갔다.

 

평소에도 프로그래밍 언어를 써가면서 연습하는 습관을 길러야겠다.