풀스택 과정 day13_Java

2022.3.24.(목)

추상화

인터페이스

Static


1. 추상화

1-1. 상속성과 다형성의 필요성

- 상속성은 객체 간의 공통적인 기능을 관리하기 위한 기법으로
  코드의 재사용을 통하여 프로그램의 유지보수를 편리하게 한다.

- 다형성( Override, Overload )은 서로 다른 기능이지만
  메서드의 이름을 공통되게 처리함으로써 전체 프로그램의
  일관성을 유지하게 한다.

1-2. Override 처리의 문제 발생 가능성

- '@Override' 키워드를 사용하지 않고 메서드를 재정의 하는
  과정에서 메서드 이름에 실수가 발생하더라도 에러가 아닌
  새로운 메서드의 정의로 인식되므로 의도하지 않은 실행결과를
  가져올 수 있다.

- '@Override' 키워드를 사용하더라도 자식 클래스를 구현하는
  개발자의 실수로 인하여 부모의 기능을 재정의 하지 않았다면
  다형성의 구현은 이루어지지 않게 된다.

1-3. 상속 처리 시, Override를 강제하기

- 추상화 기법은 특정 클래스를 상속받은 경우, 부모의 특정
  메서드들을 무조건 재정의하도록 강제하는 기법이다.

- 특정 메서드를 재정의하도록 강제함으로써, 자식 클래스들을
  작성하기 위한 가이드의 역할을 할 수 있다. 

- 즉, 추상화 기법은 java 클래스를 작성하기 위한 설계도를 
  소스코드 형태로 제시하는 역할을 한다. 

1-4. 추상 메서드 만들기

- 추상 메서드를 정의하기 위해서는 'abstract' 키워드를
  사용하여 메서드를 정의한다.

- 추상 메서드를 자식 클래스가 구현해야 하는 메서드의
  가이드라인만 제시하기 위한 목적으로 사용되기 때문에,
  선언만 가능하고 구현부가 없다.
// 일반 메서드
public void sayHello( ); {
	... 구현부 ...
};

// 추상 메서드
// 선언만 가능하고, 구현부를 위한 블록이 존재하지 않는다.
public abstract void sayHello( );

1-5. 추상 메서드를 포함한 클래스

- 추상 메서드를 하나 이상 포함하고 있는 클래스는 반드시
  '추상 클래스'로 정의되어야 한다.

- 추상 클래스 'abstract' 키워드를 사용하여 정의할 수 있다.
// 추상 클래스의 정의
public abstract class Hello {	

	public abstract void sayHello( );

}
- 추상 클래스는 객체를 생성할 수 없고, 반드시 상속을 통해서만 사용될 수 있다.
  즉, 추상 클래스는 다른 자식 클래스를 위한 '가이드라인'의 역할을 한다.
  


< 추상 메서드 sayHello를 포함한 추상 클래스 Hello >

< 추상 메서드의 Override >

1-6. 공통 기능과 설계 제기를 모두 처리하기

- 추상 클래스는 생성자, 멤버변수, 일반 메서드 등을 포함할 수 있다.

- 즉, 공통 기능과 가이드라인을 모두 정의하여 다른 클래스에게 상속된다.
public abstract class Hello {
	// 멤버변수 선언
	private String msg;

	// 생성자
	public Hello( String msg ) { this.msg = msg; }
	
	// 일반 메서드
	public String getMsg( ) { return this.msg };
	public void setMsg( String msg ) { this.msg = msg; }

	// 선언만 되고, 구현부를 위한 블록이 존재하지 않는다.
	public abstract void sayHello( );
    
}


< 추상 메서드를 포함한 부모 클래스 Unit >

< 추상 메서드를 Override한 자식 클래스 Army >

< 추상 메서드를 Override한 자식 클래스 Navy >

< 추상 메서드를 Override한 자식 클래스 AirForce >

< 추상 메서드 예제의 실행값 >


  • Navy, AirForce Class 생성, Unit 상속,
  • main( ) 포함 클래스 생성, 각각의 객체 생성 후, 메서드( attack( ), move( ) ) 호출

2. 인터페이스

public abstract class Unit {
	public abstract void attack( );		// 공격
	public abstract void shield( );		// 방어
	public abstract void walk( );		// 걷기
	public abstract void run( );		// 뛰기
	public abstract void jump( );		// 점프
	public abstract void pickup( );	// 아이템 줍기
}
- 추상 클래스인 Unit의 기능을 용도별로 분할하여 나누어 놓고,
  주인공과 몬스터가 각각의 기능 중에서 자신에게 필요한 것들만 
  상속 받도록 하는 방법을 필요로 한다.

2-1. 추상 클래스의 한계

- 자바 클래스 간의 상속에서는 하나의 부모만 존재할 수 있기 때문에,
  앞의 상황에서 요구하는 다중 상속의 구현은 불가능하다.

2-2. Interface란?

- 완벽한 추상화를 구현하기 위한 java Class의 한 종류이다.

- 다중 상속이 가능하기 때문에 용도별로 세분화 하여 필요한 요소만 상속할 수 있다.

추상 클래스	
	-> 멤버변수, 생성자, 메서드, 추상 메서드를 포함할 수 있다.
	-> 이 클래스를 상속받는 자식 클래스는 다른 클래스를 상속받을 수 없다.
	-> 객체의 생성이 불가능하다.

인터페이스	
	-> 추상 메서드만 포함할 수 있다.
	-> 인터페이스는 다중 상속이 가능하다.
	-> 객체의 생성이 불가능하다.
    


< 인터페이스 생성 이유 : 공통된 메서드나 수행될 동작을 인터페이스로 만들어 상속 받기 위해서 >

2-3. 인터페이스 상속을 위한 implements 키워드

- 인터페이스의 상속은 implements 키워드를 사용한다.

- 인터페이스도 추상화를 구현하고 있기 때문에, 인터페이스를 상속받는 클래스는
  인터페이스 내의 모든 메서드들을 반드시 재정의 해야 한다.
  


< attack( ) 메서드와 shield( ) 메서드를 가지는 Unit interface >

< Unit을 상속 받는 User 클래스 >

2-4. 인터페이스 다중 상속

- 인터페이스는 콤마( , )로 연결하여 여러 개를 동시에 상속받을 수 있다.

public class Monster implements Fight, Move {
	
} 

- 필요한 경우 다른 클래스와 동시에 상속받을 수 있다.

public class Monster extends User implements Fight, Move {
		
}



< interface의 사용 예 >


< pickup( ) 메서드를 가지는 Action interface >

< attack( ) 메서드와 shield( ) 메서드를 가지는 Fight interface >

< walk( ) 메서드와 run( ) 메서드, jump( ) 메서드를 가지는 Move interface >

< Action과 Fight, Move interface를 모두 상속 받는 Character 클래스 >

< Fight와 Move interface를 상속 받는 Monster 클래스 >

< Character와 Monster 클래스의 메서드 실행 >


3. Static

// 하나의 게시물을 표현하기 위한 클래스
// 요청사항 : 전체 글 수, 카테고리 정보
public class Article {
	private int count;			// 전체 글 수
	private String category;	// 카테고리	

	private int num;			// 글 번호
	private String title;		// 제목
	private String regDate;		// 날짜
}
- 멤버변수는 모든 객체가 독립적으로 가지는 고유 데이터이기 때문에 
  게시물의 수라는 공유 데이터를 모든 게시물이 갖게 된다.

- 즉, 각각의 객체가 중복된 데이터를 갖게 된다.

3-1. 객체 간의 공유 자원을 표현하는 static 키워드

- 클래스를 설계할 때, 멤버변수 중 모든 객체에서 공통적으로 사용해야 하는 값에
  static을 붙인다.
public class Article {
	private static int count;		// 전체 글 수
	private static String category;		// 카테고리	

	private int num;			// 글 번호
	private String title;			// 제목
	private String regDate;		// 날짜
}
- static이 붙은 멤버변수는 객체의 갯수에 상관 없이 단 하나만 생성되며,
  이를 모든 객체가 공유하기 때문에 메모리를 효율적으로 사용할 수 있다.
  


< 객체 간의 공유 자원을 이용하기 위한 static >

< static 사용 후의 모형도 >

3-2. 컴퓨터의 메모리 구조

- 코드영역(고정 영역)
	-> 프로그램의 코드가 저장되는 영역
       이 영역에 저장된 명령어들을 CPU가 하나씩 가져가 실행한다.

- 데이터 영역(고정 영역)
	-> 전역변수와 static으로 선언되는 변수가 할당된다.
       이 영역에 할당되는 변수들은 프로그램 시작과 동시에 메모리 공간이 할당되어 
       종료될 때 까지 남아있게 된다.

- 힙 영역(동적 영역)
	-> 프로그래머가 원하는 시점에 변수를 할당하고, 소멸시키는 영역
       메모리 동적 할당시 사용된다. 객체가 생성되는 영역이다.

- 스택 영역(동적 영역)
	-> 함수가 실행될 때 사용되는 파라미터와 지역변수에 대한 메모리 공간
       함수의 종료와 함께 소멸된다.

3-3. 하나의 프로그램이 사용하는 메모리 영역

- 고정 영역
	-> 프로그램이 실행되면 실행 파일이 메모리에 로드되면서,
       실행파일의 용량만큼 RAM을 사용한다.

	-> 실행 파일의 크기는 변할 수 없으므로 이 영역의 크기는 고정 크기를 갖는다.

- 동적 영역
	-> 프로그래머가 new 키워드를 사용해서 객체나 배열을 생성하면 사용된다.
       ( 힙 영역 )

	-> 또 다른 경우는 메서드가 호출되는 동안 사용될 파라미터와 지역변수가
       생성된다.( 스택 영역 )

	-> 메서드가 종료되거나 객체가 더 이상 사용되지 않으면 생성된 변수나
       객체는 메모리에서 사라지므로, 이 영역은 유동적인 크기를 갖게 된다.

3-4. static 데이터의 생성 위치

- static 데이터는 메모리의 고정 영역 중 데이터 영역에 생성되고,
  일반 멤버변수나 객체는 동적 영역 중 Heap 메모리 영역에 생성된다.

3-5. 프로그램이 메모리를 사용하는 순서

- 최초 실행시 고정 영역에 실행 파일만큼의 메모리를 점유한다.

- 프로그램이 각종 동작을 수행하는 동안 동적 영역을 사용한다. 

3-6. 멤버변수와 static 멤버변수의 차이

- static 변수는 프로그램의 실행과 동시에 객체의 생성 여부와 상관 없이
  이미 존재하기 때문에 소스코드에서는 특정 클래스 안에 명시하지만,
  그 클래스를 통해서 생성되는 객체나 그 안에 포함되는 멤버변수와는 다른 존재이다.

- 객체가 생성되지 않았더라도 이미 존재하고 있기 때문에 static 변수는 객체의
  이름을 통해 접근하는 것이 아니라, 클래스의 이름을 통해서 접근해야 한다.

- 단, static 변수가 선언된 클래스 안에서는 변수 이름으로 직접 접근이 허용된다.
- Article 클래스 및 다른 클래스에서 접근하는 경우

Article.count = 9;
Article.category = "공지사항";

- Article 클래스에서 접근하는 경우

count = 15;
category = "Q&A게시판";

3-7. static 변수와 static 메서드

- 클래스에서 정의하는 일반 메서드들은 객체의 생성과 동시에 
  동적 메모리 영역에서 활성화 된다.
	-> 동적 메모리 영역의 입장에서는 고정 메모리 영역의 자원들은 항상 존재한다.

	-> 고정 메모리 영역의 자원들은 동적 메모리의 자원들이 항상 존재하는
       것이라는 보장을 받지 못한다.

- 그러므로 객체의 생성과 상관 없이 static 변수에 접근하기 위한 메서드를 
  만들 필요가 있는데, 메서드의 정의 과정에서 static 키워드를 사용하면
  static 자원에 접근하기 위한 메서드를 만들 수 있다.
public class Article {
	private static int count;	

	public static void setCount( int count ) {
		Article.count = count;
	}

	public static int getCount( ) {
		return Article.count;
	}
}

3-8. static 메서드 사용시의 제약 사항

- 메모리 영역의 차이 때문에 static 메서드는 동적 메모리 영역의
  멤버변수를 사용하거나, static이 아닌 일반 멤버함수를 호출할 수 없다.

고정 영역
	-> static 변수와 static 멤버함수가 생성된다.

	-> 이 영역의 자원들은 프로그램이 실행되는 동안 항상 존재한다.

	-> 동적 메모리 영역의 자원들은 항상 존재하는 것이 아니기 때문에
       static 멤버함수는 동적 메모리 영역의 멤버변수를 사용하거나,
       static이 아닌 일반 멤버함수를 호출할 수 없다.

동적 영역
	-> 객체, 객체 안의 멤버변수, 메서드, 메서드가 호출되었을 때 사용되는 
       지역변수 등이 생성된다.

	-> 이 영역의 자원들은 생성과 제거가 유동적으로 반복된다.

	-> static 자원은 항상 존재하는 것이므로 동적 영역에서는 static 변수를
       활용하거나, static 멤버함수를 호출할 수 있다.

좋은 웹페이지 즐겨찾기