자바의 oop에 대하여

22277 단어 JavaOOPJava

클래스 상속

  • 개별 객체의 공통적인 부분을 모아서 상위 클래스를 만든다.
    '
    여기서 사람은 ‘메서드 저장소’ 역할을 한다고도 볼 수 있다.

  • Child class는 모두 parent-type, (그 반대는 안 됨), Parent의 모든 함수성을 상속한다, Parent class의 specialization이다.

    따라서 별다른 처리없이 부모의 메서드를 사용할 수 있다.
    또한 오버라이딩으로 다형성을 구현할 수 있다.

  	Integer intObj = new Integer(53);
  	Class c = intObj.getClass(); // call Object method

상속되는 것과 상속되지 않는 것

* 생성자, 초기화 블록, static field, static method 상속되지 않는다.
     public class Math {
      public static final double PI = 3.14159;
      //클래스(static) 상수(final)는 상속 불가능
    }
  • private/default는 상속되지만 접근 불가능

  • Protected 상속도 되고, 접근도 가능 (다른 패키지여도 가능)

  • final 키워드가 붙은 클래스는 상속이 불가능하다.

    public final class String() {}

타입 변환

  • 부모 클래스가 자식 클래스의 메서드(오버라이딩된 메서드 아님)에 접근하기 위해서는 캐스팅이 필요하다. (타입 변환)

    자바는 런타임에 타입 체크를 한다. 따라서 주의가 필요하다.

  Object obj = new Integer(38);
  System.out.println(obj.intValue()); // Compile Error

obj는 Integer를 참조하지만, Integer의 메서드는 쓸 수 없다.

레퍼런스 타입은 모두 class-type을 가지고 있으며, "참조하는 객체" 타입에 에 상관없이. 객체에 접근할 수 있는 필드와 메서드를 정의한다. 여기서 obj는 Object 타입이기 때문에 Object의 필드와 메서드만 접근 가능하다.

자식 클래스의 메서드를 쓰기 위해서는 아래와 같이 캐스팅이 필요하다.

Object obj = new Integer(453);
int i = ((Integer) obj).intValue(); // Cast obj

Parent p = new Child();   
Child c = (Child) p; //Cast p(Parent) to Child

그러나 참조하는 자식 클래스가 아닌 클래스의 메서드는 캐스팅해서도 참조할 수 없다.

Object obj = new Integer(455);
int i = ((Float) obj).floatValue(); // Runtime error

다형성과 다이나믹 바인딩

public class Parent {
	public void method() {}
}
public class Child() extends Parent {
	public void method() {}
public static void main(String[] args) {
   Parent p = new Child();
   p.method(); // Child 클래스의 method가 호출된다.

   //method를 오버라이딩한 Child2 클래스를 가정
   p = new Child2();
   p.method(); // Child2 클래스의 method가 호출된다.
    
   Child c = new Child();
   c.method(); // Child 클래스의 method가 호출된다.
    
}

비록 p가 parent type이지만 Child의 method implementation을 호출한다. 실제로 p가 가리키고 있는 것(actual type)은 Child이기 때문!

또한 p를 new Child2()를 가리키게 하면 이번에는 Child2 클래스의 메서드가 호출된다. dynamic binding속성으로 다형성의 특징을 보이는 것을 알 수 있다.

그럼 실제 부모의 클래스를 호출하려면 어떻게 해야할까?
super를 사용하면 된다.

	public class Activity {
		void onCreate() {
			System.out.println("기본적인 실행 내용");
		}
	}
	-------------------------------
	public class MainActivity extends Activity {
		@Override
		void onCreate() {
			super.onCreate(); // 부모 클래스의 onCreate 메서드 호출
			System.out.println("추가적인 실행 내용");
		}
	} 

그럼 부모 클래스의 변수를 건드리려면 어떻게해야할까?

다음과 같은 코드가 있다.

public class Task{
    private String name;
    private boolean done;
    public Task(String taskName){
        name = taskName;
        done = false;
    }
    
    public void doTask(){
        done = true;
    }
    public boolean isDone(){
        return done;
    }
}

public class FileUploadTask extends Task{
    public FileUploadTask(){
        // call parent-class constructor
        // 부모 클래스의 생성자는 상속이 안 되기 때문에 
        // super를 사용한다. 
        super("upload file");
    }
    @Override
    public void doTask(){
        //
    }
}

//main이라고 가정
Task t = new FileUploadTask();
t.doTask();

여기서 Task t의 done을 true로 바꾸려면 어떻게 해야할까? done은 private이기 때문에 접근이 불가능하다.

따라서 private에 접근할 수 있는 부모의 메서드를 호출할 수 있다.

@Override
    public void doTask(){
        super.doTask();
  	}

더 좋은 방법은 없을까? done을 protected로 선언하는 것도 괜찮겠다.

그러나 곰곰히 생각해보면 Task 자체가 doTask 메서드를 가진다는 것이 이상할 수 있다.

Task를 추상화시켜보면 어떨까?

추상 클래스

public abastract class Task{
    private String name;
    private boolean done;
    
    public Task(String taskName){
        name = taskName;
        done = false;
    }
    
    public abstract void doTask();
}

public class FileUploadTask implements Task{
    public FileUploadTask(){
       
    }
    /**Implement doTask() */
    public void doTask(){
        //
    }
}

자 다시 done를 바꿔보자.

가장 쉬운 방법은 아까처럼 done을 protected로 만드는 것이다.

혹은 Task에게 protected method를 줄 수 있다.

이렇게 되면 자식 클래스만이 task가 완료되었다고 보고 할 수 있다.

public abastract class Task{
    private String name;
    private boolean done;
    
    public Task(String taskName){
        name = taskName;
        done = false;
    }
    
    protected void reportTaskDone(){
        if(done){
            //,,,
        }
        done = true;
    }
    
    public abstract void doTask();
}

좋은 웹페이지 즐겨찾기