안녕하세요? Justkode 입니다. 오늘은 Package와 이를 Import 하는 것에 대해 알아 보겠습니다.
패키지는 클래스의 묶음 입니다. 패키지 안에는 클래스와 인터페이스를 포함 시킬 수 있습니다. 우리는 관련된 클래스를 같은 패키지에 묶어 이를 효율적으로 관리할 수 있습니다. 사실 우리는 지금까지 클래스명만 사용하여 클래스를 관리 하였지만, "패키지는 다르지만, 클래스 명이 같은 경우"를 구분 하기 위해서, 실제 이름은 패키지 명을 포함한 풀 네임을 사용 합니다.
예를 들어, String
클래스는 java.lang
패키지에 존재하는 클래스로, 풀 네임은 java.lang.String
입니다. 그래서 우리는 풀 네임을 통해서 동일 이름의 클래스라도 구별 할 수 있습니다.
패키지는 어찌보면 물리적으로 하나의 디렉토리라고 볼 수 있습니다. 클래스들이 특정 패키지에 속해 있다면, 그 클래스들은 같은 디렉토리 안에 존재 하여야 합니다. 이런 식으로 말이죠.
우리가 만든 플레이어 관련 클래스들을 모아놓은 모습 입니다.
디렉토리가 하위 디렉토리를 가질 수 있는 것 처럼, 패키지도 다른 패키지를 포함 할 수 있습니다. 이는 점 '.' 으로 구분 할 수 있습니다. 패키지의 구조는 다음 규칙을 따릅니다.
패키지를 선언 하는 방법은 다음과 같습니다.
package 패키지명
이는 주석과 공백을 제외 한 첫 번째 문장에 등장 하여야 합니다. 하나의 소스파일에는 단 한 번만 선언될 수 있으며, 해당 소스파일에 포함된 모든 클래스나 인터페이스는 선언된 패키지에 속하게 됩니다.
일단 다음과 같이 우리가 파일 디렉토리를 구성 해 보겠습니다.
디렉토리 구조.
코드는 다음과 같습니다. 전 시간에도 했던 것들이지만 정리 한다는 생각으로 싹다 정리 하고 진행 하겠습니다. 저번 시간까지 했던 기존 코드에 package player
를 추가 한 모습입니다.
player/Player.java
package player;
abstract public class Player {
private String userName;
private int healthPoint;
private int attackPoint;
private final int USER_ID;
static int objectNum;
static {
objectNum = 0;
}
{
USER_ID = objectNum++;
}
Player(String userName, int healthPoint, int attackPoint) {
setUserName(userName);
setHealthPoint(healthPoint);
setAttackPoint(attackPoint);
printUserInfo();
}
Player(Player p) {
this(p.userName, p.healthPoint, p.attackPoint);
}
public String getUserName() {return this.userName;};
public int getHealthPoint() {return this.healthPoint;};
public int getAttackPoint() {return this.attackPoint;};
public void setAttackPoint(int attackPoint) {
if (attackPoint < 0)
return;
this.attackPoint = attackPoint;
}
public void setHealthPoint(int healthPoint) {
if (healthPoint < 0)
return;
this.healthPoint = healthPoint;
}
public void setUserName(String userName) {
if (userName.length() < 2)
return;
this.userName = userName;
}
public void printUserInfo() {
System.out.println("========================");
System.out.println("플레이어 이름: " + this.userName);
System.out.println("체력: " + this.healthPoint);
System.out.println("공격력: " + this.attackPoint);
System.out.println("유저 아이디: " + this.USER_ID);
System.out.println("========================");
}
abstract public void attackPlayer(Player p);
public static void printCurrentObjectNum() {
System.out.println("현재 생성된 객체의 갯수는 " + objectNum + "개 입니다.");
}
}
player/Warrior.java
package player;
public class Warrior extends Player implements PlayerAct {
package Player;
public class Warrior extends Player implements PlayerAct {
public Warrior(String userName, int healthPoint, int attackPoint) {
super(userName, healthPoint, attackPoint);
System.out.println("직업 전사");
System.out.println("========================");
}
public Warrior(Warrior p) {
super(p);
System.out.println("직업 전사");
System.out.println("========================");
}
@Override
public void attackPlayer(Player p) {
System.out.println("========================");
System.out.printf("Player %s가 Player %s에 강력한 물리 공격%n", this.getUserName(), p.getUserName());
System.out.printf("Player %s는 %d의 피해를 입음%n", p.getUserName(), this.getAttackPoint());
p.setHealthPoint(Math.max(0, p.getHealthPoint() - this.getAttackPoint()));
System.out.printf("Player %s의 남은 체력: %d%n", p.getUserName(), p.getHealthPoint());
System.out.println("========================");
}
@Override
public void healing() {
System.out.println("========================");
System.out.printf("Player %s가 응급 키트를 이용하여 %d 포인트 만큼 회복을 시도 합니다.%n", this.getUserName(), this.HEALING_HEALTH_POINT);
this.setHealthPoint(this.getHealthPoint() + this.HEALING_HEALTH_POINT);
System.out.printf("체력이 %d가 되었습니다.%n", this.getHealthPoint());
System.out.println("========================");
}
@Override
public void buff() {
System.out.println("========================");
System.out.printf("Player %s가 극한의 정신력을 이용하여 %d 포인트 만큼 공격력을 증가 시킵니다.%n", this.getUserName(), this.BUFF_ATTACK_POINT);
this.setAttackPoint(this.getAttackPoint() + this.BUFF_ATTACK_POINT);
System.out.printf("공격력이 %d가 되었습니다.%n", this.getAttackPoint());
System.out.println("========================");
}
@Override
public void useAllSkill() {
this.healing();
this.buff();
}
}
player/Magician.java
package player;
public class Magician extends Player implements PlayerAct {
public Magician(String userName, int healthPoint, int attackPoint) {
super(userName, healthPoint, attackPoint);
System.out.println("직업 마법사");
System.out.println("========================");
}
public Magician(Magician p) {
super(p);
System.out.println("직업 마법사");
System.out.println("========================");
}
@Override
public void attackPlayer(Player p) {
System.out.println("========================");
System.out.printf("Player %s가 Player %s에 치명적인 마법 공격%n", this.getUserName(), p.getUserName());
System.out.printf("Player %s는 %d의 피해를 입음%n", p.getUserName(), this.getAttackPoint());
p.setHealthPoint(Math.max(0, p.getHealthPoint() - this.getAttackPoint()));
System.out.printf("Player %s의 남은 체력: %d%n", p.getUserName(), p.getHealthPoint());
System.out.println("========================");
}
@Override
public void healing() {
System.out.println("========================");
System.out.printf("Player %s가 마법을 사용하여 %d 포인트 만큼 회복을 시도 합니다.%n", this.getUserName(), this.HEALING_HEALTH_POINT);
this.setHealthPoint(this.getHealthPoint() + this.HEALING_HEALTH_POINT);
System.out.printf("체력이 %d가 되었습니다.%n", this.getHealthPoint());
System.out.println("========================");
}
@Override
public void buff() {
System.out.println("========================");
System.out.printf("Player %s가 마법의 힘을 증폭시켜 %d 포인트 만큼 공격력을 증가 시킵니다.%n", this.getUserName(), this.BUFF_ATTACK_POINT);
this.setAttackPoint(this.getAttackPoint() + this.BUFF_ATTACK_POINT);
System.out.printf("공격력이 %d가 되었습니다.%n", this.getAttackPoint());
System.out.println("========================");
}
@Override
public void useAllSkill() {
this.healing();
this.buff();
}
}
Main.java
에는 import player.Magician
, import player.Warrior
를 이용하여 패키지 내에 있는 클래스들을 import
해 주면 됩니다.
Main.java
import player.Magician;
import player.Warrior;
public class Main {
static public void main(String[] args) {
Warrior warrior = new Warrior("S2지존전사S2", 100, 10);
Magician magician = new Magician("S2최강법사S2", 50, 20);
warrior.attackPlayer(magician);
magician.attackPlayer(warrior);
warrior.useAllSkill();
magician.useAllSkill();
warrior.attackPlayer(magician);
magician.attackPlayer(warrior);
}
}
player
패키지 내부의 모든 클래스를 가져오고 싶다면, 다음과 같이 player.*
를 사용 할 수 있습니다.
Main.java
import player.*;
public class Main {
static public void main(String[] args) {
Warrior warrior = new Warrior("S2지존전사S2", 100, 10);
Magician magician = new Magician("S2최강법사S2", 50, 20);
warrior.attackPlayer(magician);
magician.attackPlayer(warrior);
warrior.useAllSkill();
magician.useAllSkill();
warrior.attackPlayer(magician);
magician.attackPlayer(warrior);
}
}
다음 명령어를 src
폴더 위에서 터미널을 실행 하여 입력 해 보겠습니다.
$ javac -d . player/Player.java
$ javac -d . player/Warrior.java
$ javac -d . player/Magician.java
$ javac Main.java
그러면 다음과 같이 class
파일 들이 만들어 지는 것을 확인 할 수 있습니다.
디렉토리 구조.
그 다음 해당 프로그램이 잘 돌아 가는지 테스트 해보겠습니다.
$ java Main
========================
플레이어 이름: S2지존전사S2
체력: 100
공격력: 10
유저 아이디: 0
========================
직업 전사
========================
========================
플레이어 이름: S2최강법사S2
체력: 50
공격력: 20
유저 아이디: 1
========================
직업 마법사
========================
========================
Player S2지존전사S2가 Player S2최강법사S2에 강력한 물리 공격
Player S2최강법사S2는 10의 피해를 입음
Player S2최강법사S2의 남은 체력: 40
========================
========================
Player S2최강법사S2가 Player S2지존전사S2에 치명적인 마법 공격
Player S2지존전사S2는 20의 피해를 입음
Player S2지존전사S2의 남은 체력: 80
========================
========================
Player S2지존전사S2가 응급 키트를 이용하여 10 포인트 만큼 회복을 시도 합니다.
체력이 90가 되었습니다.
========================
========================
Player S2지존전사S2가 극한의 정신력을 이용하여 10 포인트 만큼 공격력을 증가 시킵니다.
공격력이 20가 되었습니다.
========================
========================
Player S2최강법사S2가 마법을 사용하여 10 포인트 만큼 회복을 시도 합니다.
체력이 50가 되었습니다.
========================
========================
Player S2최강법사S2가 마법의 힘을 증폭시켜 10 포인트 만큼 공격력을 증가 시킵니다.
공격력이 30가 되었습니다.
========================
========================
Player S2지존전사S2가 Player S2최강법사S2에 강력한 물리 공격
Player S2최강법사S2는 20의 피해를 입음
Player S2최강법사S2의 남은 체력: 30
========================
========================
Player S2최강법사S2가 Player S2지존전사S2에 치명적인 마법 공격
Player S2지존전사S2는 30의 피해를 입음
Player S2지존전사S2의 남은 체력: 60
========================
static import
를 이용 하여, static
멤버를 호출할 때에, 다음과 같이 클래스 명을 입력 하는 것을 생략 할 수 있습니다.
import static java.lang.System.out;
import static java.lang.Math.*;
public class Main {
static public void main(String[] args) {
System.out.println(Math.random());
out.println(random());
System.out.println(Math.PI);
out.println(PI);
}
}
0.6151734216674172
0.9421767576044261
3.141592653589793
3.141592653589793
패키지는 디렉토리 구조를 가진다고 이야기 하였습니다. 그렇기 때문에, 다음과 같이 패키지내에 패키지가 존재 하는 것이 가능 합니다. 트리 구조 처럼 말이죠.
디렉토리 구조.
Battle.java
package player.battle;
import player.Player;
public class Battle {
static public void battle(Player a, Player b) {
a.attackPlayer(b);
b.attackPlayer(a);
}
}
Main.java
import static player.battle.Battle.*;
import player.Warrior;
import player.Magician;
public class Main {
static public void main(String[] args) {
Warrior warrior = new Warrior("S2지존전사S2", 100, 10);
Magician magician = new Magician("S2최강법사S2", 50, 20);
battle(warrior, magician);
}
}
이를 작성한 후, 컴파일을 실시하면 됩니다.
$ javac -d . player/battle/Battle.java
이번 시간에는 Package에 대해서 배워 보았습니다. 다음 시간에는 예외 처리, Exception에 대해서 배워 보겠습니다.