인터페이스

woom·2022년 11월 15일
0

JAVA

목록 보기
9/18
post-thumbnail

🌼 Interface

  • 인터페이스(Interface) : 현재에 존재하는 대상을 클래스보다 추상적으로 표현하기 위한 자료형 (참조형)

    • 인터페이스의 이름은 파스칼표기법을 이용하여 작성하는 것을 권장
    • 상수필드(Constant Field)와 추상메소드(Abstrac Method)만 선언 가능
    • JDK8 이상에서는 기본메소드(Default Method)와 정적메소드(Static Method)도 선언 가능
    • 형식) public interface 인터페이스명 {
      자료형 필드명=값; //상수필드(public static final 제한자 생략 가능)
      ...
      반환형 메소드명 (자료형 매개변수명, ... ); //추상메소드(public abstract 제한자 생략 가능)
      ...
      }
  • 인터페이스는 클래스에게 상수필드 또는 추상메소드를 상속

    • 다중 상속 가능 (클래스의 부모 역할 제공)
    • 형식) public class 클래스명 implements 인터페이스명, 인터페이스명,...{ }
    • 인터페이스로 객체 생성은 불가능하지만 참조변수를 생성하여 자식클래스의 객체 저장 가능
  • 인터페이스는 다른 인터페이스 상속 가능 (다중상속)

    • 형식) public interface 인터페이스명 extends 인터페이스명, 인터페이스명,...{ }
  • 인터페이스 선언하여 클래스가 상속받아 사용하는 이유

  1. 클래스의 단일 상속 관련 문제를 일부 보완하기 위해 인터페이스 사용 (다중 상속 가능)
  2. 클래스에 대한 작업지시서의 열할을 제공하기 위해 인터페이스 사용
    • ex) Tv, Radio, SmartPhone 클래스를 만든다고 했을 때 공통적인 행위 존재
      → 볼륨증가, 감소 기능을 인터페이스로 제공
    • 인터페이스를 상속받은 모든 자식클래스는 동일한 형태의 메소드가 선언되도록 규칙을 제공
    • 클래스간의 결합도를 낮춰 시스템 변경에 따른 유지 보수 효율성 증가

🎀 Q1. 클래스,인터페이스 상속

  • 부모클래스 Wolf 자식클래스 WolfHuman
  • human은 Human실체가 있는 부모 Wolf는 실체가 없는 부모 부모끼리는 객체 저장 가능 (자식 공유)

🐣 예제1 (Wolf interface)

public interface Wolf {
	//인터페이스는 추상메소드만 선언되므로 public abstract 제한자 생략 가능
	void cryLoudly();	//인터페이스는 상수필드 또는 추상메소드만 선언 가능
	void fastWalk(); }	//추상메소드



🐣 예제2 (Human class)

public class Human {
	public void speak() {
		System.out.println("[인간] 대화할 수 있는 능력");
	}
	public void walk() {
		System.out.println("[인간] 두 발로 걸을 수 있는 능력");
	}
	public void smile() {
		System.out.println("[인간] 활짝 웃을 수 있는 능력"); }}



🐣 예제3 (WolfHuman class)

  • 클래스 선언시 클래스를 상속받기 위해 extends 키워드 사용 (단일 상속)
  • 클래스 선언시 인터페이스를 상속받기 위해 implements 키워드 사용 (다중상속)
    • 인터페이스를 상속받은 클래스는 인터페이스에 선언된 모든 추상메소드를 반드시 오버라이드 선언 (실체화)

public class WolfHuman extends Human implements Wolf {
	@Override	//추상메소드 오버라이드 선언
	public void cryLoudly() {
		System.out.println("[늑대]큰 소리로 울부짖을 수 있는 능력");
	}
	@Override
	public void fastWalk() {
		System.out.println("[늑대]네발로 빠르게 달릴 수 있는 능력");
	}
	public void change() {
		System.out.println("[늑대인간]변신할 수 있는 능력"); }}



🐣 예제4 (WolfHumanApp)

  • 인터페이스(Wolf)로 참조변수(wolf)를 저장하여 자식클래스의 객체(WolfHuman) 저장 가능
  • 자식클래스가 같은 클래스와 인터페이스는 명시적 객체 형변환을 이용하여 자식클래스의 객체를 공유하여 사용 가능

public class WolfHumanApp {
	public static void main(String[] args) {
		WolfHuman wolfHuman=new WolfHuman();
		
		wolfHuman.speak();
		wolfHuman.walk();
		wolfHuman.smile();
		wolfHuman.change();
		wolfHuman.cryLoudly();
		wolfHuman.fastWalk();
		
		//부모클래스로 참조변수를 생성하여 자식클래스의 객체 저장
		// → 참조변수는 기본적으로 부모클래스의 메소드만 호출 가능
		Human human=new WolfHuman();		
		
		human.speak();
		human.walk();
		human.smile();

		//명시적 객체 형변환을 이용하여 참조변수로 자식클래스의 메소드 호출
		((WolfHuman)human).change();

		//인터페이스(Wolf)로 참조변수를 저장하여 자식클래스의 객체(WolfHuman) 저장 가능
		//Wolf wolf=new WolfHuman();
		
		//자식클래스가 같은 클래스와 인터페이스는 명시적 객체 형변환을 이용하여
        //자식클래스의 객체를 공유하여 사용 가능
		Wolf wolf=(Wolf)human;
		
		//묵시적 객체 형변환(오버라이드)에 의해 자동으로 자식클래스의 메소드 호출
		wolf.cryLoudly();
		wolf.fastWalk(); }}   
   
   
   
   
   
   

🎀 Q2. 인터페이스 다중 상속

  • 인터페이스는 다른 인터페이스를 상속받아 작성 가능
  • extends 키워드로 상속받으며 다중 상속 가능

🐣 예제1 (Boat interface)

public interface Boat {
	void navigate(); }



🐣 예제2 (Car interface)

public interface Car {
	void run();}



🐣 예제3 (BoatCar interface)

public interface BoatCar extends Boat,Car {
	void floating(); }




🐣 예제4 (BoatCarReal class)

public class BoatCarReal implements BoatCar {
	@Override
	public void navigate() {
		System.out.println("바다를 향해하는 능력");
	}
	@Override
	public void run() {
		System.out.println("땅위를 달리는 능력");
	}
	@Override
	public void floating() {
		System.out.println("공중에 떠 있는 능력"); }}





🐣 예제5 (BoatCarRealApp)

public class BoatCarRealApp {
	public static void main(String[] args) {
		//상속받은 모든 인터페이스로 참조변수를 생성하여 자식클래스의 객체 저장 가능
		//→ 묵시적 객체 형변환에 의해 오버라이드 선언된 자식클래스의 메소드 호출
		BoatCar boatCar=new BoatCarReal();
        
        boatCar.floating();		          
		boatCar.navigate();
		boatCar.run(); }}
        
        //자식클래스의 메소드를 호출하기 위해서는 명시적 객체 형변환 필요
		//Boat boatCar=new BoatCarReal(); 
		//Car boatCar=new BoatCarReal();  
        //((BoatCarReal)boatCar).run(); 
        
	
    




🎀 Q3. 메소드 작성 규칙

  • 학생 관리 클래스가 반드시 상속받아야 되는 인터페이스
  • 학생 관리 클래스의 메소드 작성 규칙 제공 (작업지시서)

🐣 예제1 (Jdbc interface)

public interface Jdbc {
	void insert();	//추상메소드 선언
	void update();
	void delete();
	void select(); }
        
    

🐣 예제2 (JdbcMysql class)

public class JdbcMysql implements Jdbc {
	@Override	//추상메소드 오버라이드 선언
	public void insert() {
		System.out.println("[mysql]학생정보를 삽입하는 메소드");
	}
	@Override
	public void update() {
		System.out.println("[mysql]학생정보를 변경하는 메소드");
	}
	@Override
	public void delete() {
		System.out.println("[mysql]학생정보를 삭제하는 메소드");
	}
	@Override
	public void select() {
		System.out.println("[mysql]학생정보를 검색하는 메소드"); }}




🐣 예제3 (JdbcOracle class)

public class JdbcOracle implements Jdbc {
	@Override	//추상메소드 오버라이드 선언
	public void insert() {
		System.out.println("[oracle]학생정보를 삽입하는 메소드");
	}
	@Override
	public void update() {
		System.out.println("[oracle]학생정보를 변경하는 메소드");
	}
	@Override
	public void delete() {
		System.out.println("[oracle]학생정보를 삭제하는 메소드");
	}
	@Override
	public void select() {
		System.out.println("[oracle]학생정보를 검색하는 메소드"); }}




🐣 예제4 (JdbcApp)

  • 자식클래스 참조변수에 객체 저장할 경우 객체간의 결합도가 높아 클래스 교체시 메소드 호출 명령 변경필요
  • 객체간의 결합도를 낮추기 위해 참조변수는 인터페이스를 이용하여 선언
public class JdbcApp {
	public static void main(String[] args) {
		/* 자식클래스 참조변수에 객체 저장할 경우
		JdbcMysql mysql=new JdbcMysql();
		
		mysql.insert();
		mysql.update();
		mysql.delete();
		mysql.select();
		
		//시스템 변경에 의해 클래스(mysql로) 교체시 메소드 호출 명령 변경
		// → 객체간의 결합도가 높기 때문에 유지보수의 효율성 감소 
		JdbcOracle oracle=new JdbcOracle();
		
		oracle.insert();
		oracle.update();
		oracle.delete();
		oracle.select();
		*/
        
		//객체간의 결합도를 낮추기 위해 참조변수는 인터페이스를 이용하여 선언
		//Jdbc jdbc=new JdbcMysql();
		//시스템 변경에 의해 클래스 교체시 메소드 호출 명령 미변경
		// → 객체간의 결합도를 낮춰 유지보수의 효율성 증가 
		Jdbc jdbc=new JdbcOracle();

		//참조변수로 인터페이스의 추상메소드를 호출하면 묵시적 객체 형변환에 의해
        //참조변수에 저장된 자식클래스 객체의 메소드를 참조하여 호출
		jdbc.insert();
		jdbc.update();
		jdbc.delete();
		jdbc.select(); }}
        
        
        
        
        

🎀 Q4. 기본메소드

  • JDK8 이상에서는 인터페이스에 명령을 작성할 수 있는 기능의 기본메소드 선언 가능
  • 기본메소드(Default Method) : 인터페이스를 상속받아 자식클래스에 오버라이드 선언하지 않아도 되는 메소드
    • 오버라이드 선언하지 않은 경우 기본메소드 호출
    • 형식) default 반환형 메소드명 (자료형 매개변수명,....) {명령;,,,}

🐣 예제1 (Printable interface)

public interface Printable {
	void print(); //추상메소드 : 자식클래스에서 반드시 오버라이드 선언
	default void scan() {
		System.out.println("[에러]스캔 기능을 제공하지 않습니다."); }}



🐣 예제2 (PrintSingle class)

public class PrintSingle implements Printable {	//Printable 인터페이스 상속
	@Override	//추상메소드 오버라이드
	public void print() {
		System.out.println("[프린트]문서를 출력합니다."); }}



🐣 예제3 (PrintMulti class)

public class PrintMulti implements Printable {//Printable 인터페이스 상속
	@Override	//추상메소드 오버라이드
	public void print() {
		System.out.println("[복합기]문서를 출력합니다.");
	}
	@Override	//기본메소드 오버라이드
	public void scan() {
		System.out.println("[복합기]문서를 스캔합니다."); }




🐣 예제4 (PrintableApp)

public class PrintableApp {
	public static void main(String[] args) {
		//기본메소드를 사용하기 위해서는 참조변수를 인터페이스로 선언
		Printable printOne=new PrintSingle();
		
		printOne.print();
		printOne.scan();	//부모 인터페이스의 기본메소드 호출

		Printable printTwo=new PrintMulti();
		
		printTwo.print();
		printTwo.scan(); }}	//오버라이드된 메소드 호출
    
    
    
    
        

🎀 Q5. 상수필드

  • 상수필드(Constant Field) 선언 : public static final 제한자 생략 가능
    • 클래스에도 선언 가능하지만 보다 쉬운 선언을 위해 인터페이스 선언
      (class에서는 public static final작성해야해)
  • 상수 (Constant) : 프로그램에서 값(리터럴) 대신 사용하기 위한 의미있는 단어 (식별자)

🐣 예제1 (InterfaceOne interface)

public interface InterfaceOne {
	int INSERT=1,UPDATE=2,DELETE=3,SELECT=4;}


    

🐣 예제2 (InterfaceTwo interface)

public interface InterfaceTwo {
	int ADD=1,MODIFY=2,REMOVE=3,SEARCH=4;}
    
   
   

🐣 예제3 (InterfaceApp)

public class InterfaceApp {
	public static void main(String[] args) {
		//인터페이스에 선언된 상수필드값 출력 (필드에 저장된 값이 제공되어 출력)
		System.out.println("삽입 = "+InterfaceOne.INSERT);//삽입 = 1
		System.out.println("변경 = "+InterfaceOne.UPDATE);
		System.out.println("삭제 = "+InterfaceOne.DELETE);
		System.out.println("검색 = "+InterfaceOne.SELECT);
		
		System.out.println("삽입 = "+InterfaceTwo.ADD);//삽입 = 1
		System.out.println("변경 = "+InterfaceTwo.MODIFY);
		System.out.println("삭제 = "+InterfaceTwo.REMOVE);
		System.out.println("검색 = "+InterfaceTwo.SEARCH);

		//상수필드에 저장된 값과 동일한 자료형(원시형)의 변수를 생성하여 상수 저장 가능
		int choice=InterfaceOne.INSERT;	//int choice=1;
		System.out.println("선택 = "+choice);

		switch (choice) {
		//case InterfaceOne.INSERT:
		case InterfaceTwo.ADD:
			System.out.println("# 학생정보를 삽입합니다. #");	
			break;
		case InterfaceOne.UPDATE:
			System.out.println("# 학생정보를 변경합니다. #");	
			break;
		case InterfaceOne.DELETE: 
			System.out.println("# 학생정보를 삭제합니다. #");	
			break;
		case InterfaceOne.SELECT: 
			System.out.println("# 학생정보를 검색합니다. #");	
			break; }}}
            
            
            
            
            
  • 인터페이스 또는 클래스에 상수필드를 선언한 경우의 단점
    • 상수필드를 값을 대표하는 단어(식별자)로 사용하기 부적절
    • 상수필드가 선언된 인터페이스 또는 클래스가 아무런 의미 없이 접근 용도로만 사용
    • 위와 같은 단점을 해결하기 위해 Java에서 열거형(enum)이라는 자료형(참조형)을 제공

🌼 Enumerate

  • 열거형 (Enumerate) : 상수만을 선언하기 위한 자료형(참조형)

    • 형식) public enum 열거형 {상수명, 상수명, ....;}
    • 열거형의 이름은 파스칼표기법을 이용하여 작성하는 것을 권장
  • 열거형의 상수필드에는 0부터 1씩 증가되는 저장값이 기본값으로 자동 저

    • public static final int 생략 가능
  • 열거형에 선언된 상수필드값 출력 시 상수의 이름이 제공되어 출력

    • 프로그램에서 상수가 값을 대표하는 이름으로 사용 가능
  • 열거형에 선언된 상수를 저장하기 위해서는 반드시 열거형을 이용하여 변수 선언

    • 상수가 선언된 열거형을 하나의 자료형으로 사용 가능

🎀 Q1. 열거형 (기본)

🐣 예제1 (EnumOne enum)

public enum EnumOne {
	INSERT, UPDATE, DELETE, SELECT; }	//상수필드 선언
    
    

🐣 예제2 (EnumTwo enum)

public enum EnumTwo {
	ADD, MODIFY, REMOVE, SEARCH; }	//상수필드 선언
    
    

🐣 예제3 (EnumApp)

public class EnumApp {
	public static void main(String[] args) {
		//열거형에 선언된 상수필드값 출력 (상수의 이름이 제공되어 출력)
		// → 프로그램에서 상수가 값을 대표하는 이름으로 사용 가능
		System.out.println("삽입 = "+EnumOne.INSERT);//삽입 = INSERT
		System.out.println("변경 = "+EnumOne.UPDATE);
		System.out.println("삭제 = "+EnumOne.DELETE);
		System.out.println("검색 = "+EnumOne.SELECT);

		System.out.println("삽입 = "+EnumTwo.ADD);	//삽입 = ADD
		System.out.println("변경 = "+EnumTwo.MODIFY);
		System.out.println("삭제 = "+EnumTwo.REMOVE);
		System.out.println("검색 = "+EnumTwo.SEARCH);

		//열거형에 선언된 상수를 저장하기 위해서는 반드시 열거형을 이용하여 변수 선언
		// → 상수가 선언된 열거형을 하나의 자료형으로 사용 가능
		//int choice=EnumOne.INSERT;//에러 발생
		EnumOne choice=EnumOne.INSERT;//EnumOne 자료형에 선언된 상수만 저장 가능한 변수
		System.out.println("선택 = "+choice);	//선택=INSERT

		//나열형으로 선언된 참조변수에 비교값은 같은 자료형의 상수만 사용하여 비교 가능
		switch (choice) {
		case INSERT:
		//case ADD:	EnumOne 자료형에 선언된 상수만 저장 가능하기 때문에 에러발생
			System.out.println("# 학생정보를 삽입합니다. #");	
			break;
		case UPDATE:
			System.out.println("# 학생정보를 변경합니다. #");	
			break;
		case DELETE: 
			System.out.println("# 학생정보를 삭제합니다. #");	
			break;
		case SELECT: 
			System.out.println("# 학생정보를 검색합니다. #");	
			break; }}}
           
           
           

🎀 Q2. 열거형 (매개변수)

  • 나열형에 선언된 상수필드는 기본적으로 정수형(int)으로 설정
  • 상수필드를 선언하면 기본생성자를 이용하여 초기화 (0부터 1씩 증가되는 정수값 사용)
  • 매개변수가 작성된 생성자를 선언하면 기본생성자자는 제공되지 않으므로 상수 선언 불가능
  • 상수필드의 자료형 또는 상수필드에 저장되는 값을 변경하기 위해서는 필드 선언
    • private final 제한자를 사용하여 선언
    • 필드에 저장된 값을 이용하여 상수필드값을 변경하기 위해 반드시 생성자 선언

    🐣 예제1 (Compass enum)

public enum Compass {
	//EAST, WEST, SOUTH, NORTH; :매개변수 없으므로 기본생성자 제공
	
	//매개변수가 선언된 생성자를 이용하여 상수필드 선언
	EAST("동"),WEST("서"),SOUTH("남"),NORTH("북");//필드, 생성자 선언 필수
	
	//상수필드의 자료형 또는 상수필드에 저장되는 값을 변경하기 위해서는 필드 선언
	// → 필드에 저장된 값을 이용하여 상수필드값을 변경하기 위해 반드시 생성자 선언
	private final String value;	//상수필드를 표현하기 위한 대표필드
	
	//private final 제한자로 선언된 대표필드에 초기값을 설정하기 위한 생성자
	// → 생성자를 반드시 은닉화 선언
	// → 매개변수로 전달값을 대표필드에 저장 (상수필드 초기화)
	private Compass(String value) {
		this.value=value;
	}
	//대표필드에 대한 Getter 메소드 (상수필드에 저장된 값을 반환하는 메소드)
	public String getValue() {
		return value; }}



🐣 예제2 (CompassApp)

  • EnumType.values() : 열거형에 선언된 모든 상수필드를 배열로 변환하는 메소드
  • EnumType.ordinal() : 상수필드를 구분하기 위한 첨자(Index)를 반환하는 메소드
public class CompassApp {
	public static void main(String[] args) {
		//상수필드값 출력 - 상수필드명을 제공받아 출력
		System.out.println("동쪽 = "+Compass.EAST);//동쪽 = EAST
		System.out.println("서쪽 = "+Compass.WEST);
		System.out.println("남쪽 = "+Compass.SOUTH);
		System.out.println("북쪽 = "+Compass.NORTH);

		//대표필드값을 반환받아 출력 (상수필드에 저장된 값을 제공받아 출력)
		System.out.println("동쪽 = "+Compass.EAST.getValue());//동쪽 = 동
		System.out.println("서쪽 = "+Compass.WEST.getValue());
		System.out.println("남쪽 = "+Compass.SOUTH.getValue());
		System.out.println("북쪽 = "+Compass.NORTH.getValue());

		//EnumType.values() : 열거형에 선언된 모든 상수필드를 배열로 변환하는 메소드
		for(Compass compass:Compass.values()) {
			//EnumType.ordinal() : 상수필드를 구분하기 위한 첨자를 반환하는 메소드
			System.out.println(compass+"="+compass.getValue()+":"+compass.ordinal());
            }}} //EAST=동:0 , WEST=서:1 ···
            
            
            
            
            

        
profile
Study Log 📂

0개의 댓글

관련 채용 정보