일반 데이터 타입의 배열과 동일한 개념으로, 같은 클래스의 객체 여러개를 그룹화 할 수 있다.
일반 데이터형의 배열 생성과 객체 배열 생성 비교
일반 데이터 형 배열의 경우
int [ ] data = new int [3];
객체 배열의 경우
Army[ ] data = new Army[3];
일반 데이터형은 단순히 값을 대입하지만, 객체 배열은 'new'라는 키워드를 사용해서 객체를 할당해야 한다.
일반 데이터 형 배열의 경우
data[0] = 1;
data[1] = 2;
data[2] = 3;
객체 배열의 경우
data[0] = new Army( );
data[1] = new Army( );
data[2] = new Army( );
배열의 생성이 부모 클래스로 지정되었을 경우, 모든 자식 클래스의 객체들은 그 배열에 포함될 수 있다.
Unit[ ] unit = new Untit[3];
Unit[0] = new Army( );
Unit[1] = new Navy( );
Unit[2] = new AirForce( );
for( int i = 0; i < unit.length; i++ ) {
unit[i].attack( );
}
원래의 기능으로 복귀하기
-> 배열의 각 요소가 확장을 사용하기 위해서는 원래의 클래스 형태로 명시적 형변환이 이루어 져야 한다.
-> 하지만 반복적으로 처리되는 과정에서 몇 번째 요소가 어떤 클래스에서 최초 생성 되었는지를 판단하기란 쉽지 않다.
instanceof 연산자
-> instanceof 연산자는 어떤 객체에 대한 출처를 판단하여 boolean 형으로 결과를 반환한다.
if ( unit[0] instanceof Army ) {
Army temp = (Army)unit[0];
}
package boxing;
public class Main01 {
// 부모 클래스에 대한 객체 배열을 생성하고 배열의 요소에
// 자식 클래스 객체를 할당하면, 자동으로 암묵적 형변환이 이루어진다.
public static void main(String[] args) {
// 부대 지정
Unit [] units = new Unit[5];
units[0] = new AirForce("공군1호");
units[1] = new AirForce("공군2호");
units[2] = new Navy("해군1호");
units[3] = new Army("육군1호");
units[4] = new Army("육군2호");
// 부대 일괄 공격
for (int i = 0; i < units.length; i++) {
units[i].attack();
// instanceof
if (units[i] instanceof Army) {
Army a= (Army)units[i];
a.tank();
} else if (units[i] instanceof Navy) {
Navy b= (Navy)units[i];
b.nucleus();
} else {
AirForce f= (AirForce)units[i];
f.bombing();
}
}
}
}
package boxing;
public class AirForce extends Unit {
public AirForce (String name) {
super (name);
}
public void attack() {
super.attack();
System.out.println(this.getName() + ">> 이륙");
System.out.println(this.getName() + ">> 공중공격 실행");
}
public void bombing() {
System.out.println(this.getName() + ">> 폭격");
}
}
package boxing;
public class Army extends Unit {
public Army(String name) {
super(name);
}
// Override 메서드
// 공격의 형태를 육군에 맞게 변경하지만, 부모 클래스가 가지고 있는 공격 준비
// 기능을 super 키워드를 재사용해서 호출하려고함
@Override
public void attack() {
super.attack();
System.out.println(super.getName() + ">> 지상공격 실행함");
}
public void tank() {
System.out.println(super.getName() + " >>탱크 공격");
}
}
package boxing;
public class Navy extends Unit {
public Navy (String name) {
super(name);
}
public void attack() {
super.attack();
System.out.println(this.getName() + ">> 해상공격 실행함");
System.out.println(this.getName() + ">> 지상 상륙");
}
public void nucleus() {
System.out.println(this.getName() + ">> 핵미사일");
}
}
package boxing;
public class Unit {
private String name;
public Unit(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void attack() {
System.out.println(this.name + ">>> 공격준비");
}
}
추상 메서드를 정의하기 위해서는 'abstract' 키워드를 사용하여 메서드를 정의한다.
추상 메서드는 자식 클래스가 구현해야 하는 메서드의 가이드라인만 제시하기 위한 목적으로 사용되기 때문에 선언만 가능하고 구현부가 없다.
public abstract void move( );
package interfaceobject;
public class Character implements Action, Fight, Move{
private String name;
public Character(String name) {
super();
this.name = name;
}
public void walk() {
System.out.println(this.name + ">> 걷다" );
}
@Override
public void run() {
System.out.println(this.name + ">> 뛰다" );
}
@Override
public void jump() {
System.out.println(this.name + ">> 점프" );
}
@Override
public void attack() {
System.out.println(this.name + ">> 공격" );
}
@Override
public void shield() {
System.out.println(this.name + ">> 방어" );
}
package interfaceobject;
public class Monster implements Fight, Move {
private String name;
public Monster(String name) {
super();
this.name = name;
}
@Override
public void walk() {
System.out.println(this.name + ">> 걷다" );
}
@Override
public void run() {
System.out.println(this.name + ">> 뛰다" );
}
@Override
public void jump() {
System.out.println(this.name + ">> 점프" );
}
@Override
public void attack() {
System.out.println(this.name + ">> 공격" );
}
@Override
public void shield() {
System.out.println(this.name + ">> 방어" );
}
}
package interfaceobject;
// 인터페이스 정의
public interface Unit {
/*
* 기본적으로 인터페이스에 추가되는 모든 메서드는 추상 메서드이기 때문에,
* 'abstract' 키워드를 명시할 필요가 없다.
*/
public void attack();
public void shield();
}
package interfaceobject;
public interface Action {
// 줍다
public void pickup();
}
package interfaceobject;
public interface Fight {
//공격
public void attack();
//방어
public void shield();
}
package interfaceobject;
public class Main01 {
public static void main(String[] args) {
Character ch = new Character("주인공");
ch.walk();
ch.run();
ch.attack();
ch.shield();
ch.pickup();
System.out.println("--------------");
Monster mon = new Monster("괴물");
mon.run();
mon.walk();
mon.shield();
mon.attack();
}
}
추상 메서드를 하나 이상 포함하고 있는 클래스는 반드시 '추상 클래스' 로 정의되어야 한다.
추상 클래스는 'abstract' 키워드를 사용하여 정의할 수 있다.
public abstract class Hello {
public abstract void move( );
}
추상 클래스는 객체를 생성할 수 없고, 반드시 상속을 통해서만 사용될 수 있다. 즉 추상 클래스는 다른 자식 클래스를 위한 '가이드라인'의 역할을 한다.
추상 클래스는 생성자, 멤버변수, 일반 메서드등을 포함할 수 있다.
즉 공통 기능과 가이드라인을 모두 정하여 다른 클래스에게 상속된다.
public abstract class Hello {
//멤버변수
private String msg;
// 생성자
public Hello ( String msg ) { this.msg = msg; }
// 일반 메서드
public String getMsg( ) { retrun this.msg; }
// 선언만 되고, 구현부를 위한 블록이 존재하지 않는다.
public abstract void sayHello( );
}