국비지원 복습과정 8차(객체배열, 추상화)

Park In Kwon·2022년 9월 15일
0

1. 객체배열

1-1. 객체 배열이란

  • 일반 데이터 타입의 배열과 동일한 개념으로, 같은 클래스의 객체 여러개를 그룹화 할 수 있다.

  • 일반 데이터형의 배열 생성과 객체 배열 생성 비교

    일반 데이터 형 배열의 경우
    int [ ] data = new int [3];

    객체 배열의 경우
    Army[ ] data = new Army[3];

1-2. 각 경우에 대한 배열의 요소 할당 처리

  • 일반 데이터형은 단순히 값을 대입하지만, 객체 배열은 'new'라는 키워드를 사용해서 객체를 할당해야 한다.

    일반 데이터 형 배열의 경우
    data[0] = 1;
    data[1] = 2;
    data[2] = 3;

    객체 배열의 경우
    data[0] = new Army( );
    data[1] = new Army( );
    data[2] = new Army( );

1-3. 부모 클래스의 배열에 자식 클래스의 객체를 넣기

  • 배열의 생성이 부모 클래스로 지정되었을 경우, 모든 자식 클래스의 객체들은 그 배열에 포함될 수 있다.

    Unit[ ] unit = new Untit[3];
    Unit[0] = new Army( );
    Unit[1] = new Navy( );
    Unit[2] = new AirForce( );

1-4. 객체 배열의 활용

  • 일괄처리가 가능
    -> 서로 다른 객체를 부모 형태의 배열에 담게 되면, 반복문으로 일괄처리가 가능하다.
    -> 이 때 배열의 각 요소를 통해 사용하는 메서드가 Override되어있을 경우, 부모의 메서드가 아니라 자신이 재정의한 기능을 뜻한다.
        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 + ">>> 공격준비");
	}
}

2. 추상화

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

  • 상속성은 객체간의 공통적인 기능을 관리하기 위한 기법으로, 코드의 재사용을 통하여
    프로그램의 유지보수를 편리하게 한다.
  • 다형성(Override, Overload)는 서로 다른 기능이지만 메서드의 이름을 공통되게 처리함으로서
    전체 프로그램의 일관성을 유지하게 한다.

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

  • '@Override' 키워드를 사용하지 않고 메서드를 재정의하는 과정에서 메서드 이름에 실수가
    발생하더라도 에러가 아닌 새로운 메서드의 정의로 인식되므로 의도하지 않은 실행결과를 가져올 수 있다.
  • '@Override' 키워드를 사용하더라도 자식 클래스를 구현하는 개발자의 실수로 부모의 기능을 재정의
    하지 않았다면, 다형성의 구현은 이루어지지 않게 된다.

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

  • 추상화 기법은 특정 클래스를 상속받은 경우, 부모의 특정 메서드들을 무조건 재정의하도록 강제하는 기법이다.
  • 특정 메서드를 재정의하도록 강제함으로써, 자식 클래스들을 작성하기 위한 가이드의 역할을 할 수 있다.
  • 즉, 추상화 기법은 java 클래스를 작성하기 위한 설계도를 소스코드 형태로 제시하는 역할을 한다.

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

  • 추상 메서드를 정의하기 위해서는 '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();
	}
}

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

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

  • 추상 클래스는 'abstract' 키워드를 사용하여 정의할 수 있다.

    public abstract class Hello {

    public abstract void move( );

    }

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

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

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

  • 즉 공통 기능과 가이드라인을 모두 정하여 다른 클래스에게 상속된다.

       public abstract class Hello {
               //멤버변수
               private String msg;
    
               // 생성자
               public Hello ( String msg ) { this.msg = msg; }
    
               // 일반 메서드
               public String getMsg( ) { retrun this.msg; }
    
               // 선언만 되고, 구현부를 위한 블록이 존재하지 않는다.
               public abstract void sayHello( );
       }
profile
개발자로 진로 변경을 위해 준비하고 있습니다

0개의 댓글