'상속'에 해당되는 글 1건

  1. 2007.09.11 몇가지 단어에 대한 이야기

상속
재사용 즉, 효율적인 코드를 반복 사용하기 위해 등장한 개념으로, 보통 상속의 개념을 생각하면 쉽게 이해가 되는 의미이다.

자바에서는 순수하게 하나의 클래스에게서만 상속받을 수 있으며, 이를 단일 상속이라고 하며, 예약어로 extends 를 사용한다.

다음과 같은 class가 있다고 가정을 하자.
class A {
    int a = 100;
}
누군가가 다음과 같은 class A가 마음에 들어 그것을 가져다 쓰고 싶다면, 다음과 같은 식으로 사용하면 된다.
class B {
    A ap = new A();
    int b = 200;
}
이렇듯 하나의 클래스 내부에 다른 클래스의 객체를 포함하고 있는 형태를 포함 Object 라고 한다. 굳이 상속을 사용하지 않더라도 자연스럽게 다른 클래스를 재사용할 수 있다. 하지만 문제는 다음과 같은 상황에서 발생한다.

또다른 누군가가 class A를 재사용한다고 한다면 이렇게 된다.
class C {
    B bp = new B();
    int c = 300;
}
또다른 누군가가 재사용한다면..
class D {
    C cp = new C();
    int d = 400;
}
이렇게 된다면, 다음과 같은 경우, 문제가 발생한다. a라는 멤버의 값을 출력하라고 한다면??
D dp = new new D();
System.out.println("a = " + dp.cp.bp.ap.a);
원칙대로라면 정확한 사용법이지만, 과연 이런식의 작성이 효율적일지는 생각해 봐야 한다. 만약 이보다 더 늘어날 경우, 프로그램은 대책없이 커지게 될테니까.

이러한 문제점을 해결하기 위해 등장한 개념이 바로 상속이다.

자바의 API 를 살펴본다면, java.lang 이라는 패키지 안에 Object 라는 클래스가 있는데, Object 클래스는 어느 누구에게도 상속을 받지 않고 있으며, 이는 바로 Object 클래스가 최상위, 부모 클래스라는 것을 의미한다. 이 의미는 즉, Object 를 제외한 모든 클래스(interface 제외)가 Object 클래스에게서 상속을 받는 다는 의미가 된다.

이 Object 클래스는 상속관계가 적혀 있지 않은 모든 클래스를 자동적으로 java.lang.Object 클래스가 상속되었다고 JVM 이 인식하고 있으므로 생략이 가능하다.

다음과 같은 소스를 살펴 보자
1//    class Inherit extends Object {

2//    }

3//    public class Round13_Ex01 extends Object {
4//        public static void main(String[] ar) {
5//           Inherit in = new Inherit();
6//           System.out.println("두 객체가 같니? " + in.equals(in));
7//        }
8//    }
Inherit 클래스는 아무것도 내용이 적혀 있지 않은 클래스다. 5번째 라인에서는 객체를 생성시 아무런 생성자도 없다면 default 생성자가 있는 것으로 JVM 이 인식하기 때문에 아무런 에러 메시지도 없으면서 잘 실행 된다.

다음 라인인 6번째 라인에서의 in.equals(in) 이 문제인데, 객체 메서드를 보면 먼저 in을 발생시킨 클래스 내에서 equals() 메소드를 찾아야 한다. 그러나 in 이라는 객체를 발생시킨 Inherit 클래스 내부에는 아무것도 없다. 그렇다면 당연히 에러메세지가 출력이 되어야 하지만, 상위 클래스로부터 물려받았을 수도 있기 때문에 그 클래스에게 상속을 준 상위 클래스로 거슬러 올라가야 한다.

Inherit 에게 상속한 상위클래스는 생략되어 있는 Object 클래스이며, 이 클래스 안에는 equals() 라는 메소드가 있기에, 에러가 발생하지 않는 것이다.

이렇듯 상속이란, 이미 작성되어 있던 내용들을 마치 내가 만든 것처럼 다시 사용할수 있게 만드는 개념이다.

상속에서는 이렇게 메소드를 찾아 나가는데, 먼저 해당 객체의 클래스부터 먼저 뒤져보고, 없으면 그 다음의 상위 클래스로 찾아 올라가고, 그렇게 찾아 올라가다, 끝까지 가서도 못찾으면 그때서야 에러가 발생하게 된다.

상속받은 하위 클래스에서는 상위 클래스의 멤버를 마치 자신의 멤버인 양 사용할수 있으며, 모든 클래스의 최상위에는 Object 클래스가 있다는 것을 염두해 두어야 한다.

또 한가지, super 라는 예약어는 상위클래스의 멤버를 지칭할때 사용하는 예약어이며, this 는 현재 클래스의 자기 자신을 의미하는 예약어이다.

상속에서의 몇가지 특징은

1. 상속받는 class 는 상속해 주는 class 의 private 와 생성자를 제외한 모든 것을 상속받는다.
2. 단일 상속만 가능
3. protected 는 상속받는 클래스에서 접근이 가능
4. 상속받는 클래스에서 객체를 생성하면, 상위클래스와 자신의 생성자를 모두 호출


오버라이드
메서드의 상속에서 동일한 이름의 메서드가 상위 클래스와 하위 클래스에 동시에 존재하는 것을 보고 오버라이딩이라고 한다.
class A2 {
    public void disp() {
       System.out.println("A2 클래스");
    }
}

class B2 extends A2 {
    public void disp() {
       super.disp();      // A2 클래스의 disp() 메서드를 호출
       System.out.println("B2 클래스");
    }
}
여기에서 A2 클래스와 B2 클래스안에는 동일한 이름의 메서드가 있다. 이때 B2 클래스의 disp() 메소드를 보고 오버라이딩되었다라고 한다.

이렇듯 오버라이딩은 상속관계에서 상위클래스와 하위클래스에서 동일한 이름의 메서드가 있는 것을 보고 이야기 하는 것이다.

여기에는 두가지 중요한 규칙이 있다.

1. 오버라이딩을 할 때에는 접근 제한자의 범위가 같거나 커야 한다.
private < package < protected < public

2. 오버라이딩된 하위 클래스의 메서드에 throws 구문이 있으면 상위 클래스의 오버라이딩을 준 메서드도 반드시 해당 예외 클래스에 준하는 throws 구문이 있어야 한다.

이 두가지 규칙을 위반하면 에러가 발생한다.
class A {
    private void aaa() {...}
}

class B extends A {
    private(package, protected, public) void aaa() {...}
}
상위 클래스의 메소드를 오버라이딩 하려고 할 때 그 메소드가 private 이면 하위 클래스에 오버라이딩 되는 메서드의 접근 제한자로는 private, package, protected, public 네가지 모두 된다는 뜻이다. 만약 상위 클래스의 메소드가 package 라면 하위 클래스의 메소드는 package, protected, public 세가지가 될수 있고, protected 라면 protected 와 public 두가지만 된다. 이렇게 되는 것이 첫번째 규칙이다.

class A {
    public void aaa() throws Exception{...}   // 상위 클래스의 메소드에 예외 구문이 있다면)
}

class B extends A {
    public void aaa() {...}   // throws 구문이 있어도 되고 없어도 된다.
}


반면
class A {
    public void aaa() {...}    // 아래와 같다면, 상위 클래스에서 throws 가 반드시 있어야 한다.
}

class B extends A {
    public void aaa() throws Exception {...}   // 하위 클래스의 메서드에 예외구문이 있다면..
}

이것이 두번째 규칙이다.

오버라이딩이 되면, 하위클래스의 오버라이딩 된 메소드가 실행이 된다.


Polymorphism(다형성)
1. 여러개의 개별적인 클래스를 하나의 부모 클래스 객체로 통합 관리하여 그 효율성을 높인 것.
2. 필드는 무조건 상위 클래스의 필드만 사용할 수 있다.
3. 메서드도 상위 클래스의 메서드만 사용할 수 있는데 오버라이딩이 되었다면 하위 클래스의 메서드가 실행된다.

다형성을 사용하는 이유는??? 확실하지는 않지만...



Abstract Class
1. 다형성에서 특별한 할일이 없이, 단지 클래스들을 하나로 묶어주는 역할만 할때 사용
2. 일반 클래스의 모든 기능을 할수 있으나, 자신의 객체만큼은 발생시키지 못한다.
3. 만약 충상 클래스가 추상 메서드를 가지고 있다면 그것은 반드시 오버라이딩이 되어야 한다.


Abstract Method
1. 추상 메소드는 ; 로 끝이남
2. 반드시 오버라이딩이 되어야만 하며, 그렇지 않을 경우, 이 메소드를 포함하는 클래스 역시, 추상 클래스를 상속 받아, 추상 클래스가 되어, 객체를 발생시키지 못한다.
3. 직접 객체를 발생시킬 필요가 없고 단지 상속에 의해서 하위 클래스만 제어할 목적일때 사용한다.


Interface
1. 자바에서는 단일 상속만 가능하며, 이로 인해 불편함을 개선하고자 등장한 다중 상속의 개념이 바로 인터페이스
2. 인터페이스 혹은 클래스등, 같은 유형간의 상속에는 extends 라는 예약어를, 인터페이스가 클래스에게 상속할 때는 implements 라는 예약어를 사용하나, 클래스가 인터페이스에게 상속할 수는 없다.
3. 필드는 무조건 public static final 로 인식
4. 메소드는 무조건 public abstract 멤버 메소드로 인식.
5. 중첩 클래스에는 자동적은 static 이 붙는다.
6. 인터페이스 내에 있을 수 있는 멤버는 위에 3가지를 제외하고는 없다.
7. 생성자도 없다.
8. 추상 메서드를 포함하고 있기 때문에 객체를 발생시킬수도 없다.


이상, 다시 공부해 나갈때 다시 정리하겠음... -0-
:

BLOG main image
아무거나 공부하자!!! by Young79

공지사항

카테고리

분류 전체보기 (79)
Programing (29)
English (31)
Graphic (4)
Saying on T"We"tter (15)

최근에 올라온 글

최근에 달린 댓글

글 보관함

달력

«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total :
Today : Yesterday :