코딩 기록들

[Java Programming] 9.1 추상화, 인터페이스 본문

Java

[Java Programming] 9.1 추상화, 인터페이스

코딩펭귄 2024. 1. 29. 16:30

추상화

- 추상의 사전적 의미 : 여러가지 사물이나 개념에서 공통되는 특성이나 속성따위를 추출하여 파악하는 작용

 + 사물을 어떤 성질, 공통성, 본질에 착안하여 그것을 추출 & 파악하는것 (=클래스), 그 때 다른 성질을 배제하는 작용인 사상을 수반하므로 추상과 사상은 동일작용의 두 측면을 형성함

ex) 여러것들을 가져와서 다른것, 같은것을 뽑아내어 따로 정리해서 빼놓음

      -> 공통된것들은 써두고(추상클래스), 다른것들은 어떻게 쓰일지 모르니 비워둠

(실무에서는 추상클래스 잘 쓰지 않는다)

 

추상클래스

- 어떤기능의 공통부분은 모두 구현해놓고(추상), 다른부분들만 구현하지 않은 (사상)메소드가 있는 클래스

구현하지 않은 메소드= abstract method

구현하지 않은 클래스 = abstract class

 

환불기능이 있는 자판기 & 일반 자판기 

(공통된 기능 = 추상) : 돈넣고 -> 버튼누르고 -> 출력한다

돈통(멤버변수)을 만들고 -> 돈넣고 -> 버튼누르고 -> 출력하고 -> 환불기능(-> 사상, private로 만든다)을 만든다

          (환불 = 버튼을 누를때 재고가 없다면 환불해주는것 즉, 버튼누르는 기능에서 환불기능 호출)

자판기의 추상 클래스

- abstract method가 있을경우 : 클래스의 타입도 abstract class가 되어야한다.

- abstract class는 인스턴스로 만들수가 없다. (new Seller => 식의 이용이 안된다)

- {}부분이 없으므로 어떻게 행동해야될지 모름 -> abstract class 상속받은 곳에서 overriding 해서 사용해야됨

 

 

- 추상메소드 : 기능구현이 되어있든, 되어있지않든 호출가능함

 

(추상화내용 피피티 교재에있는거 보지말기)

 추상화의 이점

- 인터페이스나 추상클래스만으로 코드작성이 가능

- 다형성 : 하나의 인터페이스나 추상클래스로 여러개의 구현클래스 만들수있고

- 여러개의 구현클래스를 이용해 유연한 상황대처가 가능함

 

--> 껍데기만 추상화시키는 '완전 추상화' 방법을 더 많이 이용한다 : 인터페이스!

추상화 vs 인터페이스

- 추상클래스와 인터페이스는 :추상메소드를 만든다는 점에서 동일 (일반적으로, 추상메소드의 비율로 추상화정도 나타냄)

- 추상클래스 : class - 비완전 추상화(추상메소드와 일반메소드가 혼재할 가능성 매우높음)

- 인터페이스 : interface - 완전추상화, 추상메소드만 존재함

  (인터페이스가 추상클래스보다 추상화의 정도가(유연함의 정도가) 높음 = side effect가 발생하지 않을 확률이 높다)

 

추상클래스의 활용

- 기존코드를 확장하려 할 때 : 기존코드는 수정하지않고, 추상클래스를 활용해 코드 전후에 해야할일 작성

인터페이스의 활용

- 제공되는 기능에대해서는 알고있지만, 환경(OS, DB,사용자 입력값 등 )별로 기능의 구현이 변경되어야 할 때

 


 

인터페이스

개발자의 약속 : '이형태(인터페이스)로 만들고 이형태로 호출해주세요 !!'

- 추상(유연함)의 정도가 높다 = side effect가 낮다 = 사상의 정도 즉, 구현시키지않은것들이 얼마나많이 있는가

 

1. 추상클래스 : 추상된(이미 구현된) 메소드가 존재함 -> 그 중 일부가 사상된 메소드(구현안된것들) => 100%의 사상된 클래스가 존재하지 않음 (실무에서는 사이드이펙트가 높기때문에 사용하지 않음)

2. 인터페이스 : 100% 사상의 정도를 보장함 = 전부다 구현이 안되어있고, 오직 '기능의 껍데기'만 제공함

- windows 운영체제, 키보드, 모니터, 마우스 등등의 정해진 '규격' : 인터페이스

- 인터페이스가 제공해주는걸 우리가 쓸 수 있다 (= 인터페이스가 제공하지않는것들은 우리가 쓸 수 없다)

- 개발 코드와 객체가 서로 통신하는 접점 역할을 함

--> 개발코드 : 인터페이스의 메소드 호출 -> 메소드 : 객체의 메소드 호출 => 개발코드는 인터페이스의 메소드만 알고있어도 됨

사용자 인터페이스 User Interface

UI란, 사람과 컴퓨터 시스템&프로그램 간 상호작용을 의미한다.

API Application Programming Interface

- 운영체제와 응용프로그램 사이의 통신에 사용되는 언어나 메시지 형식 ex) 자바, C++, Pascal등

- API는 프로그래머를 위한 운영체제나 프로그램의 인터페이스

 

인터페이스 정의에서 공통으로 나오는 주제

- 우리가 사용할 인터페이스는 :  1. 연결, 2.상호작용ex)파라미터, 3.메시지 를 모두 만들어줘야한다

자바 인터페이스의 의미

1. 클래스와 클래스가 상호작용할수 있도록 '표준'을 제공

2. 개발자간 커뮤니케이션을위한 표준 제공

인터페이스는 '다형성' 제공

- IS A 관계가 제공이 됨 ex)모니터, 키보드, 마우스 등등의 예시와 비슷한 맥락

- 하나의 인터페이스를 이용해 여러개의 클래스를 생성할수있다

* 다형성 : TV, 리모콘이 통신하는 표준규격을 통해 여러형태의 리모콘이 TV와 연결될수 있다 (TV가 제공하지않는 기능은 리모콘도 못한다!)

 

인터페이스 이름 작성법

- 정석) 형용사로

- 보통은) 명사로 많이 만든다

- 영어대소문자 구분, 첫글자대문자, 나머지는 소문자로 작성

 

- 인터페이스는 오로지 추상메소드와 상수의 정의를 위해 사용 (=상수필드추상메소드만을 구성멤버로 가짐)

- 인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없음 (단, 자바1.8부터는 Default Abstract Method 쓸수있지만, 많이 안씀)

 

 

상수필드 선언

- 인터페이스에는 객체사용방법을 정의한것이므로 실행시 데이터 저장을 할수있는 인스턴스, 정적필드는 선언불가능.

  하지만, '상수필드' 는 선언이 가능

[public static final] 타입 상수이름 = 값;

 

추상메소드 선언

- 인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행됨 -> 인터페이스의 메소드는 실행블록이 필요없는 추상메소드로 선언함 

- 인터페이스에 선언된 추상메소드는 모두 public abstract의 특성을 갖기때문에, 생략하더라도 컴파일과정에서 자동으로 붙게됨

[public abstract] 리턴타입 메소드이름(매개변수, ...);

 

 

인터페이스 구현 (순서)

- 1) 개발코드 : 인터페이스 메소드 호출

-> 2) 인터페이스 : 객체의 메소드 호출

-> 3) 객체 : 인터페이스에서 정의된 추상메소드와 동일한 메소드이름, 매개타입, 리턴타입을가진 실체 메소드를 가지고있어야함 (= 인터페이스 구현객체)

-> 4) 구현객체를 생성하는 클래스 = 구현클래스 라고 함

 

 

0.인터페이스 선언은 class 키워드 대신, interface키워드를 사용

인터페이스의 메소드는 실행블록이 필요없는 추상에소드(리턴타입, 메소드명, 매개변수만 기술 & {} 중괄호 없음)로 선언

[public] interface SomeInterface {   
    [public abstract] void(리턴타입) doSomething1(); //abstract 생략가능
}

 

1.인터페이스에 상수 선언가능 _(상수명은 대문자로 작성. 선언과 동시에 초기화 반드시 해야됨)

[public static final ] 타입 상수명 = 값;

 

2. 인터페이스를 만든 후 구현클래스를 만들어줌 (인터페이스는 직접 인스턴스화(객체화) 할 수 없으므로 '구현클래스'가 반드시 필요함) --> 인터페이스 구현할때 : implements 키워드 사용함

public class SomeClass implements SomeInterface {
}

 

 

(참고) 클래스와 인터페이스를 함께 상속 할 때

클래스명 extends 클래스명 implements 인터페이스명, ... 인터페이스명 

( extends, implements 순서 헷갈리지 말것 )

 

(참고) 구현클래스

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

-> 구현클래스가 작성되면, new연산자로 객체 생성할 수 있음 (구현 객체를 인터페이스 변수에 '대입' 해서 사용)

 

3.인터페이스의 메소드는 SomeClass에서 반드시 구현해줘야됨 - SomeClass에 SomeInterface 구현

public class SomeClass implements SomeInterface {
    @Override
    public void doSomething1() { … }
}

-> SomeInterface와 SomeClass가 완성됨. 인터페이스와 구현클래스 사이도 IS A 관계(SomeClass is a SomeInterface)가 성립함. 따라서 아래와 같은 인스턴스 정의가 가능해짐

public static void main(String[] args) {
    SomeInterface some = new SomeClass(); //SomeInterface에서 제공하는 기능만 쓸수있음
    some.doSomething1();
    
    int something = some.getSomething();
    System.out.println(something);
}

 

클래스와 인터페이스 간 상속 조합
클래스 extends 클래스{...} 인터페이스 extends 인터페이스 [...]
클래스 implements 인터페이스 {...} 인터페이스 extends/implements 클래스{...}

- 같은 타입끼리는 extends, 다른타입끼리는 implements 사용 (단, 인터페이스는 클래스 상속 불가능)

표현주의) 클래스 A가 인터페이스 B를 상속했다 = 클래스 A가 인터페이스 B를 구현했다

 

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

- 객체는 다수의 인터페이스 타입으로 사용할 수 있음

- 인터페이스 A, 인터페이스 B가 객체의 메소드를 호출할 수 있으려면, 객체는 A, B두 인터페이스를 모두 구현해야함

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

* 다중 인터페이스를 구현할 경우, 구현클래스는 모든 인터페이스의 추상메소드에 대해 실체 메소드를 작성해야함 *

 

예제

1. Unit 인터페이스
public interface Unit {   //인터페이스에 존재하는 모든 메소드는 추상메소드이므로 abstract 생략할수있다
	//기본커맨드 : 이동, 정지, 홀드, 정찰
	/**
	 * 이동
	 */
	public void move();
	/**
	 * 정지
	 */
	public void stop();
	/**
	 * 홀드
	 */
	public void hold();
	/**
	 * 정찰
	 */
	public void patrol();
}

2. Attackable 인터페이스
//인터페이스도 상속 할 수 있다 : extends
/**
 * 공격가능한 유닛 인터페이스.
 * *****인터페이스는 인터페이스만 상속할수있다.******
 */
public interface Attackable extends Unit {
	public void attack();
}

3. SpecialCommand 인터페이스
public interface SpecialCommand extends Attackable{
	//마린, 파이어백 이라는 스팀팩? 이 있음
	public void steampack(); //공격가능한 유닛만 쓸수있음	
}
4. SpecialCommand 인터페이스
public class Marine implements SpecialCommand {

	@Override
	public void attack() {
		// TODO Auto-generated method stub
		System.out.println("공격");
	}

	@Override
	public void move() {
		System.out.println("Move! Move! Move!");
	}

	@Override
	public void stop() {
		System.out.println("정지");
	}

	@Override
	public void hold() {
		System.out.println("움직이지 않아요");		
	}

	@Override
	public void patrol() {
		System.out.println("정찰하세요");		
	}

	@Override
	public void steampack() {
		System.out.println("더 빠르게 공격~!");		
	}

	public static void main(String[] args) {
		// 인터페이스를 구현한 클래스라면, 클래스의 타입은 인터페이스여야 함 -> 그래야 인터페이스의 타입?역할을? 제한시킬수있음
		// 아래 3줄은 모두 IS A 관계 성립함
		SpecialCommand marine1 = new Marine(); //specialCommand를 쓸수있는 marine 객체 만들기
		Unit marine2 = new Marine(); 
		Attackable marine3 = new Marine(); //marine3은 steampack을 제외한 모든것 쓸수있음
		
		marine1.steampack();
		marine2.move();
		marine3.attack();
	}
}

5. Minable 인터페이스
//Scv를 위한 인터페이스
public interface Mineable {

	/**
	 * 채굴
	 */
	public void mining();
}

6. Scv 인터페이스
public class Scv extends Marine
					implements Attackable, Unit, Mineable{ 
	
//	/// 이건 인터페이스와는 아무런 관련이 없는 기능
//	-> 이렇게 따로 작성하는것이 아닌, 별도의 인터페이스를 만들어야 됨
//	public void mining() {
//		System.out.println("자원을 캡니다.");
//	}
	//인터페이스(Attackable, Unit)가 상속받는 관계가 아닐때,
	// 여러개의 인터페이스를 컴마(,)로 이어붙여 구현 가능
	@Override
	public void mining() {
		System.out.println("자원을 캡니다.");	
	}
	@Override
	public void attack() {
		System.out.println("공격");	
	}
	@Override
	public void move() {
		System.out.println("이동");		
	}
	@Override
	public void stop() {
		System.out.println("정지");
		
	}
	@Override
	public void hold() {
		System.out.println("홀드");	
	}
	@Override
	public void patrol() {
		System.out.println("정찰");
	}
}
public class Game {

	public static void move(Attackable unit) {
		unit.attack();
		unit.move();
		unit.stop();
		unit.hold();
		unit.patrol();
//		unit.mining(); //불가능. Attackable에는 mining이 없기 때문
		
		// 잘못된 호출방법.
		// 이렇게 하면 mining 사용할수 있기는 하지만, 
		// 인터페이스가 제공하지않는 기능을 억지로 제공하려고 하는
		// 코드이기 때문에 아래와 같은 형태로 사용하지말것
//		if (unit instanceof Scv) {
//			Scv scv = (Scv) unit;
//			scv.mining();
//		}
		
		if (unit instanceof Mineable) {  // 좌향unit의 객체가 우향 Mineable의 인스턴스라면, true 리턴 
			Mineable worker = (Mineable) unit;
			worker.mining();
		}	
	}
	
	public static void main(String[] args) {
		
		//익명클래스 만들기 (한번쓰고 안쓸 클래스 쉽게 만드는 방법)
		// Stream API(함수형 자바) 사용할 때 주로 사용되는 방법
		Mineable drone = new Mineable() {

			@Override
			public void mining() {  //인터페이스를 가지고 한번쓰고 안쓸 익명클래스 만드는것
				System.out.println("드론이 미네랄을 채굴합니다.");
			}
		};
		drone.mining();

		// 추상화가 되어있는 인터페이스 = 구현되어있는 클래스 형태!
		SpecialCommand marine = new Marine();
		
		Attackable scv = new Scv();
		
		marine.attack();
		marine.steampack();
		marine.move();
		marine.steampack(); //가능
		
		scv.attack();
		scv.patrol();
		scv.hold();
		//scv.mining();//은 쓸 수 없다 -> 인터페이스는 인터페이스가 제공하는 기능만을 쓸 수 있음.
		//즉, Attackable은 mining 이라는 기능을 만들어놓지 않았기 때문에 불가능함
		//scv.steampack(); // 불가능
		move(scv);
		move(marine);	
	}
}

 

 

 

 

Github 관련

  • github (원격)
  • branch : 원본이나 복사본 관리하는것
  • master : 최신상태의 원본만 관리하는것
  • commit = 코드를 stage 로 올리겠다 (이과정에서 틀린코드 발견하면 올리고 내리면서 관리할수있음)
  • push : stage에 있는것을 master로 올리는것 
  • pull :깃헙에있는 코드를 나에게 가져오는것 (stage로 가져옴)