[혼공자]5주차

박수연·2025년 8월 24일

[혼공자]

목록 보기
5/7

08인터페이스

08-1 인터페이스

  • 코드와 객체가 서로 통신하는 접점 역할
  • 개발 코드를 수정하지 않고 사용하는 객체를 변경할 수 있도록 하기 위해 사용

인터페이스 선언

  • 물리적 형태는 클래스와 동일
  • interface 키워드 사용
    [public interface 인터페이스이름 {…}]
  • 인터페이스는 상수, 필드, 추상 메소드 만을 구성 멤버로 가진다
  • 객체를 생성할 수 없기 때문에 생성자를 가질 수 없다
interface 인터페이스이름{
// 상수
타입 상수이름 = 값;
// 추상 메소드
타입 메소드이름(매개변수, …);
}

상수 필드 선언

  • 인터페이스는 데이터를 저장할 수 있는 인스턴스, 정적 필드를 선언할 수 없다
  • 상수필드는 선언 가능하며 고정된 값으로 실행 시에 바꿀 수 없다
  • public statc final로 선언, 생략해도 자동으로 붙음
  • 관례적으로 상수 이름은 대문자로 작성하고 선언과 동시에 초기값 지정

추상 메소드 선언

  • 리턴 타입, 메소드 이름, 매개 변수만 기술되고 중괄호{}를 붙이지 않는 메소드
  • public abstract 키워드 사용, 생략해도 컴파일 과정에서 자동으로 붙음

인터페이스 구현

  • 인터페이스는 구현 클래스가 있어야 하고, 구현 클래스에는 인터페스이에 정의된 추상 메소드와 동일한 메소드가 있어야 한다.
  • 구현 클래스에 의해 성성되는 객체를 구현 객체라 한다

구현 클래스

  • 인터페이스 타입으로 사용 가능함을 알려주는 implements 키워드를 추가하고 인터페이스 이름을 명시해야한다
  • 추상 메소드의 실체 메소드를 선언해야 한다
public class 구현클래스이름 implements 인터페이스이름{
// 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}
  • 인터페이스의 모든 메소드는 기본적으로 public 접근 제한을 갖기 때문에 public 보다 더 낮은 접근 제한으로 작성할 수 없다 public을 생략하면 컴파일 에러가 발생한다
  • 구현클래스가 작성되면 new 연산자로 객체를 생성 할 수 있다
  • 인터페이스로 구현 객체를 사용하려면 인터페이스 변수를 선언하고 구현 객체를 대입해야 한다
    인터페이스 변수;
    변수 = 구현객체;
    인터페이스 변수 = 구현객체;

다중 인터페이스 구현 클래스

public class 구현클래스이름 implements 인터페이스A, 인터페이스B {
// 인터페이스 A에 선언된 추상 메소드의 실체 메소드 선언
// 인터페이스 B에 선언된 추상 메소드의 실체 메소드 선언
}

인터페이스 사용

  • 인터페이스는 개발코드와 구현 객체 사이에서 접점 역할을 한다.
  • 클래스를 선언할 때 인터페이스는 필드, 생성자 또는 메서드의 매개 변수, 생성자 또는 메소드의 로컬 변수로 선언될 수 있다.
  • 개발 코드는 인터페이스에 선언된 추상 메소드를 호출하고 인터페이스는 구현 객체의 재정의 메소드를 호출한다

08-2 타입변환과 다형성

  • 프로그램 개발할 때 인터페이스를 이용했다면, 프로그램 코드는 변함없이 구현 객체를 교체함으로써 실행결과가 다양해지는데 이것이 인터페이스의 다형성이다

자동 타입 변환

  • 구현 객체가 인터페이스 타입으로 변환되는것은 자동 타입 변환에 해당한다
  • 필드와 매개변수의 타입을 인터페이스로 선언하면 자동 타입 변환을 이용해 실행결과를 다양하게 만들 수 있다.

필드의 다형성

  • 클래스 구성 시, 필드값으로 인터페이스의 구현 객체를 대입할 수 있다.
  • 객체 생성 후, 초기값으로 대입한 구현 객체 대신 다른 구현 객체를 대입할 수도 있다.
  • 이때 클래스 구성 시 필드값으로 넣은 구현 객체와 객체 생성시 대입한 구현 객체가 다르기 때문에 다른 메소드가 호출되어 다른 실행결과를 가지게 된다 이게 필드의 다형성이다

매개 변수의 다형성

  • 메소드를 만들 때, 매개 변수를 인터페이스 타입으로 선언하고 호출할 때 구현 객체를 대입하면 대입되는 구현 객체에 따라 메소드 실행 결과가 다양해질 수 있다 이것이 매개 변수의 다형성이다

강제 타입 변환

  • 구현 객체가 인터페이스 타입으로 자동 타입 변환하면 인터페이스에 선언된 메소드만 사용 가능하다는 제약 사항이 있다.
  • 경우에 따라 구현 클래스에 선언된 필드와 메소드를 사용해야 하는 겅우도 있는데 이때 강제 타입 변환을 해서 다시 구현 클래스 타입으로 변환한 다음 구현 클래스의 필드와 메소드를 사용할 수 있다

객체 타입 확인

  • instanceof 연산자를 사용
    객체 instanceof 확인할 타입
if(vehicle instanceof Bus){		
	Bus bus = (Bus) vihicle;  	
}

09 중첩 클래스와 중첩 인터페이스

09-1 중첩 클래스와 중첩 인터페이스 소개

  • 중첩 클래스 : 클래스 내부에 선언한 클래스
  • 중첩 클래스를 사용하면 두 클래스의 멤버들을 쉽게 접근 할 수 있고, 다른 불필요한 관계로 인한 코드의 복잡성을 줄일 수 있다

중첩 클래스

  • 멤버 클래스 : 클래스의 멤버로서 선언되는 중첩 클래스, 클래스나 객체가 사용 중이면 언제든지 재사용이 가능
  • 로컬 클래스 : 생성자 또는 메소드 내부에서 선언되는 중첩 클래스, 메소드를 실행할 때만 사용되고 메소드가 종료되면 없어짐
  • 중첩 클래스도 하나의 클래스이므로 컴파일 하면 바이트 코드 파일이 별도로 생성

    멤버 클래스
    A $ B .class
    로컬 클래스
    A $1 B .class
    * A : 바깥 클래스, B : 멤버 혹은 로컬 클래스

인스턴스 멤버 클래스

  • 인스턴스 멤버 클래스는 static 키워드 없이 중첩 선언된 클래스
  • 인스턴스 멤버 클래스는 인스턴스 필드와 메소드만 선언이 가능하고 정적 필드와 메소드는 선언할 수 없다

정적 멤버 클래스

  • 정적 멤버 클래스는 static 키워드로 선언된 클래스를 말한다. 모든 종류의 필드와 메소드를 선언할 수 있다

로컬 클래스

  • 메소드 내에서 선언하는 중첩 클래스
  • 접근 제한자(public, private) 및 static을 붙일 수 없다(메소드 내부에서만 사용되므로 접긎 제한이 필요 없음)
  • 인스턴스 필드와 메소드만 선언 가능

중첩 클래스의 접근 제한

바깥 필드와 메소드에서 사용 제한

  • 바깥 클래스에서 인스턴스 멤버 클래스를 사용할 때 제한이 있다
  • static 초기화 블록이나 static 메소드에서는 static 중첩 클래스만 사용할 수 있다.

멤버 클래스에서 사용 제한

  • 인스턴스 멤버 클래스 안에서는 바깥 클래스의 모든 필드와 모든 메소드에 접근 가능
  • 정적 멤버 클래스 안에서는 바깥 클래스의 정적 필드와 정적 메소드에 접근 가능하지만 인스턴스 필드와 인스턴스 메소드에는 접근 불가능

로컬 클래스에서 사용 제한

  • 로컬 클래스에서 메소드의 매개변수나 로컬 변수를 사용할 때, 그 값을 로컬 클래스 내부에 복사(메소드 실행이 끝나면 매개변수와 로컬 변수는 스택 프레임에서 사라지기 때문)해둔다.
  • 이러한 이유료 자바7 이전에는 매개 변수나 로컬 변수를 final로 선언할것을 요구했지만 자바8부터는 final 선언하지 않아도 final의 특성을 부여하도록 바뀌었다

중첩 클래스에서 바깥 클래스 참조 얻기

  • 중첩 클래스 내부에서 this 키워드를 사용하면 중첩 클래스의 객체 참조가 된다
  • 중첩 클래스 내부에서 바깥 클래스의 필드와 메소드에 참조하기 위해서는 바깥클래스.this.필드 혹은 바깥클래스.this.메소드(); 이렇게 사용해야 한다

중첩 인터페이스

  • 클래스의 멤버로 선언된 인터페이스를 중첩 인터페이스라 한다
  • 인스턴스 멤버 인터페이스와 정적 멤버 인터페이스 모두 가능

09-2 익명 객체

  • 익명 객체 : 이름이 없는 객체로 클래스를 상속하거나 인터페이스를 구현해야만 한다
    부모클래스 변수 = new 부모클래스() { … };
    인터페이스 변수 = new 인터페이스() { … };

익명 자식 객체 생성

  • 자식 클래스가 재사용 되지 않는 경우 익명 자식 객체를 생성해서 사용
부모 클래스 [필드|변수] = new 부모클래스(매개값, …){
	// 필드
    // 메소드
};
  • 익명 자식 객체에서 새롭게 정의된 필드와 메소드는 익명 자식 객체 내부에서만 사용되고, 외부에서는 접근할 수 없다
class A {
  Parent field = new Parent()	{
    int childField;
    void childMethod(){}
    @Override
    void patentMethod(){
      childField = 3;
      childMethod();
    }
  };
  
  void method() {
    field.childField = 3; 	← X 
    field.childMethod(); 	← X
    field.parentMethod(); 	← O
  }
}
  • 위 코드에서 childField와 childMethod()는 parentMethod() 내에서는 사용이 가능하지만 A클래스의 필드인 field로는 접근할 수 없다

익명 구현 객체 생성

  • 특정 위치에서만 구현 클래스를 사용하는 경우에는 익명 구현 객체를 생성해서 사용하는 것이 좋은 방법이다
인터페이스 [필드|변수] = new 인터페이스() {
  // 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
  // 필드
  // 메소드
}
  • 중괄호{}에는 인터페이스에 선언된 모든 추상 메소드의 실체 모스드를 작성해야 한다
    * 추가로 필드와 메소드를 선언할 수 있지만, 실체 메소드에서만 사용 가능하고 외부에서는 사용불가

익명 객체의 로컬 변수 사용

  • 메소드의 매개변수나 로컬 변수를 익명 객체 내부에서 사용할 때, 그 값을 익명 객체 내부에 복사(메소드 실행이 끝나면 매개변수와 로컬 변수는 스택 프레임에서 사라지기 때문)해둔다.
  • 이러한 이유료 자바7 이전에는 매개 변수나 로컬 변수를 final로 선언할것을 요구했지만 자바8부터는 final 선언하지 않아도 final의 특성을 부여하도록 바뀌었다

과제

  • 기본과제
    클래스를 선언할 때 인터페이스는 어떻게 선언될 수 있는지 정리하기(코드 작성해보기)
public interface Book {
	public int maxPage = 500;
	public int minPage = 0;
	
	public void bookOpen();
	public void bookClose();
	public void nextPage();
	public void prevPage();
	public void nowPage(int page);	
}

public interface Note {
	public void takeNote();
}

public class WepDevelop   implements Book, Note{
public int page = 0;
	
	public void bookOpen(){
		System.out.println("책을 펼칩니다.");
	}
	
	public void bookClose(){
		System.out.println("책을 덮습니다.");
	}
	
	public void nextPage(){
		if(page >= maxPage){
			System.out.println("마지막 페이지 입니다");
		}else{
			System.out.println("다음 페이지로 넘어갑니다.");
			page++;
		}
	}
	
	public void prevPage(){
		if(page <= minPage){
			System.out.println("첫번째 페이지 입니다");
		}else{
			System.out.println("이전 페이지로 돌아갑니다.");
			page--;
		}
		
	}
	
	public void nowPage(int page){
		System.out.println("현재 " + page + "페이지 입니다");
	}
	
	public void takeNote() {
		System.out.println("노트정리를 합니다.");		
	}
}

0개의 댓글