7장 import문과 제어자, 캡슐화, 다형성

slee2·2021년 9월 7일
0

Java의 정석

목록 보기
12/28
post-thumbnail
post-custom-banner

import문

  • 클래스를 사용할 때 패키지이름을 생략할 수 있다.
  • 컴파일러에게 클래스가 속한 패키지를 알려준다.
  • java.lang패키지의 클래스는 핵심패키지여서 import하지 않고도 사용할 수 있다.
    String, Object, System, Tread ...
  • import문은 패키지문과 클래스선언 사이에 선언한다.
class	ImportTest {
	java.util.Date today = new java.util.Date();
}

---- 위처럼 전부 써야하지만 import를 쓰면 -------

import java.util.Date;

class	ImportTest {
	Date	today = new Date();
}

혹시나 코드를 작성할때 패키지가 어디에 있는지 찾을 수 없어 오류가 뜰때 이클립스에서
ctrl + shift + o를 누르면 찾아준다.

static import문

  • static멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다.
import static java.lang.Integer.*;		// Integer클래스의 모든 static메서드
import static java.lang.Math.random;	// Math.random()만. 괄호 안붙임.
import static java.lang.System.out;		// System.out을 out만으로 참조가능

System.out.println(Math.random()); ---> out.println(random());

제어자

  • 클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여
    접근 제어자 - public, protected, (default), private
    그 외 - static, final, abstract, native, transient, synchronized, volatile, strictfp

  • 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)

public	class	ModifierTest {
	public static final	int	WIDTH = 200;

	public static void	main(String[] args) {
   		System.out.println("WIDTH=" + WIDTH);
    }
}

static - 클래스의, 공통적인

class	StaticTest {
------- 간단 초기화 ---------
	static int	width = 200;		// 클래스 변수(static 변수)
   	static int	height = 120;		// 클래스 변수(static 변수)
------ 복잡한 초기화 ---------
	static {		// 클래스 초기화 블럭
   		// static변수의 복잡한 초기화
    }
    
   	static int	max(int a, int b) {	// 클래스 메서드(static 메서드)
   		return a > b ? a : b;
    }
}

final - 마지막의, 변경될 수 없는

------ 조상이 될 수 없는 클래스 -----
final class	FinalTest {
-------- 상수(멤버변수) -----------
	final int	MAX_SIZE = 10;
    
----- 오버라이딩할 수 없는 메서드 -----
   	final void	getMaxSize() {
-------- 상수(지역변수) ------------
   		final int	LV = MAX_SIZE;
   		return MAX_SIZE;
    }
}

abstract - 추상의, 미완성의

--------- 미완성 설계도 ----------
abstract class	AbstractTest {	// 추상 클래스(추상 메서드를 포함한 클래스)
	abstract void	move();		// 추상 메서드(구현부가 없는 메서드)
    미완성 메서드
}

--------- 제품 생성불가 ----------
AbstractTest	a = new AbstractTest();	// 에러. 추상 클래스의 인스턴스 생성불가

접근 제어자(access modifier)

private

  • 같은 클래스 접근 가능

(default)

  • 같은 패키지 접근 가능

protected

  • 같은 패키지 + 다른 패키지의 자손 접근 가능

public

  • 제한x
class	MyParent {
	private		int	prv;	// 같은 클래스
   			int	dft;	// 같은 패키지
  	protected	int	prt;	// 같은 패키지 + 자손(다른 패키지)
   	public		int pub;	// 접근제한 없음.
    
   	public void	printMembers() {
   		System.out.println(prv);	// OK
   		System.out.println(dft);	// OK
   		System.out.println(prt);	// OK
   		System.out.println(pub);	// OK
    }
}

public class	MyParentTest {
	public static void	main(String[] args) {
   		MyParent	p = new MyParent();
   		System.out.println(p.prv);	// 에러.
   		System.out.println(p.dft);	// OK
   		System.out.println(p.prt);	// OK
   		System.out.println(p.pub);	// OK
    }
}

캡슐화와 접근 제어자

접근 제어자를 사용하는 이유

  • 외부로부터 데이터를 보호하기 위해서
  • 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서
public class Time {
----------- 캡슐화 -----------
	private	int	hour;
   	private	int	minute;
   	private	int	second;
-------- 메서드는 public ------
	public	int	getHour() {return hour;}
   	public	void	setHour(int hour) {
   		if (hour < 0 || hour > 23) return;
  		this.hour = hour;
   	}
}

다형성(좀 중요)

  • 여러가지 형태를 가질 수 있는 능력
  • 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
    Tv t = new SmartTv(); // 타입 불일치
class	Tv{
	boolean	power;
   	int	channel;
    
   	void	power()	{power = !power;}
   	void	channelUp() {++channel;}
   	void	channelDown() {--channel;}
}

class SmartTv extends Tv {
	String	text;
   	void	caption() {}
}

SmartTv	s = new SmartTv();	// 참조 변수와 인스턴스의 타입이 일치
Tv	t = new SmartTv();	// 조상 타입 참조변수로 자손 타입 인스턴스 참조

실제 멤버가 7개라고 해도 5개밖에 사용하지 못한다.

자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다.

Tv	t = new SmartTv();	// 허용
SmartTv	s = new Tv();		// 에러

자손의 멤버 개수가 부모보다 많기 때문에 부모기준으로 할당이 되었을 때, 자손에서 가리키려는 멤버가 없기 때문에 에러가 나온다.

참조변수의 형변환

  • 사용할 수 있는 멤버의 갯수를 조절하는 것
  • 조상 자손 관계의 참조변수는 서로 형변환 가능
class	Car {
	String	color;
   	int	door;
    
   	void	drive() {	// 운전하는 기능
   		System.out.println("drive, Brrr~");
    }
   	void	stop() {	// 멈추는 기능
   		System.out.println("stop!!");
    }
}

class	FireEngine extends Car {	// 소방차
	void	water() {	// 물을 뿌리는 기능
		System.out.println("water!!!");
	}
}

public class Drive {
	public static void	main(String[] args) {
		FireEngine	f = new FireEngine();
		
		Car		c = (Car)f;		// Ok. 조상으로 형변환
		FireEngine	f2 = (FireEngine)c;	// OK. 자손으로 형변환
        	Ambulance	a = (Ambulance)f;	// 에러. 상속관계가 아니면 형변환 불가
	}
}

또, 형변환을 할때 변환 전에 있던 값들은 남아있다.

이렇게 했을때, f2.a에 값을 주고 형변환을 두번한 후에 다시 출력해보면 값이 남아있다. 또, 처음 할당이 자손으로 되었는지 조상으로 되었는지도 중요하다.

Car는 조상이다. 조상에는 멤버가 4개 자손은 5개있다. 여기서 처음 할당할때 4개의 멤버가 만들어지고 그 형변환을 자손이 받는다 이때 조상에 없는 자손의 메소드를 실행하면, 컴파일은 성공했다고 착각을 하지만 실제로 실행했을때, 오류가 나온다. 조상에 자손의 메소드가 없기 때문이다.

instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
  • 형변환 전에 반드시 instanceof로 확인해야 함
void	doWork(Car c) {
	if (c instanceof FireEngine) {			// 1. 형변환이 가능한지 확인
   		FireEngine	fe = (FireEngine)c;	// 2. 형변환
   		fe.water();
  		...

매개변수의 다형성(다형성의 장점1)

  • 참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
class Product {
	int	price;		// 제품가격
	int	bonusPoint;	// 보너스점수
}

class	Tv extends		Product {}
class	Computer extends	Product {}
class	Audio extends		Product {}

class	Buyer {	// 물건사는 사람
	int	money = 1000;	// 소유금액
	int	bonusPoint = 0;	// 보너스점수
//	void	buy(Tv t)
//	void	buy(Computer t)
//	void	buy(Audio t)
	void	buy(Product	p) {
		money -= p.price;
		bonusPoint += p.bonusPoint;
	}
}

public class Buyman {

	public static void main(String[] args) {
		Buyer	b = new Buyer();
		
		Tv	tv = new Tv();
		Computer	com = new Computer();
		
		b.buy(tv);
		b.buy(com);
	}
}

여러 종류의 객체를 배열로 다루기(다형성의 장점2)

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product	p1 = new Tv();
Product	p2 = new Computer();
Product	p3 = new Audio();
------------------------------
Product	p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
class Product {
	int	price;		// 제품가격
	int	bonusPoint;	// 보너스점수
}

class	Tv extends	Product {}
class	Computer extends	Product {}
class	Audio extends	Product {}

class	Buyer {	// 물건사는 사람
	int	money = 1000;	// 소유금액
	int	bonusPoint = 0;	// 보너스점수
   
  	Product[]	cart = new Product[10];	// 구입한 물건을 담을 배열
    
   	int	i = 0;
    
	void	buy(Product	p) {
		if(money < p.price) {
   			System.out.println("잔액부족");
  			return ;
   		}
   		money -= p.price;
   		bonusPoint += p.bonusPoint;
   		cart[i++] = p;
	}
}

배열은 Vector클래스가 최고다. 배열의 단점중의 하나가 한번 크기를 정하면 바꿀수가 없다라는 것인데 벡터는 그 단점을 보안해줄 수 있다.

post-custom-banner

0개의 댓글