자바 공부<2> - 상속,캡슐화,오버라이딩,오버로딩,final,static,this(),super()

Posted by oimb
2018. 7. 2. 23:06 JAVA

 

 

 

자바 공부 <1> 에 이어서 <2>로 넘어가겠습니다.

 

 

 

1. 상속

 

상속에 앞서 클래스의 종류를 논리적?으로 나눠보자

 

1. has a

사람은 핸드폰을 가지고 있다    =>   객체의 소유여부,포함관계를 나타낸다

시람은 핸드폰이다  => ??!

2. is a

디지털 카메라는 핸드폰의 종류이다  =>  종속, 상속 관계를 나타낸다.

디지털 카메라는 핸드폰을 가지고있다  => ???

 

1 번은 단순하게 객체의 소유 여부 이지만 2번의 클래스의 경우에는 상속관계를 나타낸다.

상속의 개념을 좀더 확고하게 사용할려면 2번의 경우처럼 클래스를 사용하는것이  좋아 보인다.

 

상속의 개념을 이용하여 클래스를 작성 할 경우 여러가지 이점이 있지만 몇가지 제시하면

 

1. 재사용성 증가

2. 중복성이 감소 되어 간결성이 증가

3. 이로인해 시간이 절약

 

이렇게 3가지 장점이 있다고 생각 된다.

 

다음으로  JAVA는 다중 상속을 지원하지 않는다.  

왜? 많은 이유들이 책과 인터넷에 있지만 단순하게 생각하면 된다

다중 상속이 많아지면 그 클래스는 복잡성이 올라가고 애매모호함이 증가한다  이는  상속을 쓰는 장점이 사라진다고 보면 된다.

 

그리고 앞서 설명한 JVM 메모리 구조에 대한 설명을 하자면

하위 클래스 (자식)가 인스턴스 생성을 위해 호출이 되면 상위 클래스(부모)가 먼저 생성된다는 점에 유의하자

 

 

2. 캡슐화

 

캡슐화는 객체의 속성을 내부에 하나로 묶고 감싸 외부에 보여지지 않게하는것이라고 생각하면된다. 이는 객체 지향의 특징이다. 이로써 정보은닉(블랙박스) 효과를 볼수 있다.

 

이러한 캡슐화를 하는 개인적 사견을 붙이면 

캡슐화는 보안을 위해서는 아닌것 같다. 왜냐하면 디컴파일러하면 전부다 볼수있는 세상이기 때문인데 이것 하나로 보안을 보장하기에는 무리가 있어보인다.

단지 클래스 내부에 기능적 매서드가 무엇이 있는지에 대해서 알아야 할 필요 없이 그 클래스 자체가 무엇인가에 대해서 초점을 맞추자는 것이다.

다만 중요 몇가지 특성에 있어서는 알려줄 필요도 있다. 

이러한 내 사견은 역시나 개발의 편의성을 증가 시켜주기 위해서라고 생각한다.

 

 

3. 오버 라이딩  -  오버 로딩

 

먼저 둘을 간단하게 정리하면  오버 로딩은 기존에 존재하지 않는 새로운 매서드를 정의하는것 , 오버라이딩은 상속 받은 매서드의 내용을 변경하는것 

이다.

 

따라서 

먼저 오버 로딩은 1. 이름은 같지만  2. 매개변수의 개수 또는 타입이 달라야 한다. 주의 할점은 리턴타입이 다르면 오버로딩 아닌가?라고 햇갈릴수 있는데 리턴타입이 다르더라도 위 2가지가 성립하지 않으면 오버로딩이 아니다.

 

오버라이딩은 1. 이름은 같고 2. 매개변수도 같고  3. 반환타입이 같아야 한다. 즉 선언부가 일치해야 한다는것

다만 제한하에 다를 수 있는 부분이 있다  접근제어자 , 예외의 개수 , static 이 있다.

 

1. 접근제어자

조상 클래스의 메서드보다 좁은 범위로 변경 할 수없다
publicc > protected > (default) > private  순으로  하나의 접근 제어자에서 오른쪽 갈수 없다고 생각하면 된다

 

2. 예외 개수

조상 클래스의 매서드 throws IOExce...,SQLExc...  이 있다 할때 이 매서드를 오버라이딩 하는것의 예외 개수가 더 많아선 안된다

 

3. static

인스턴스 매서드   <------>   스태틱 매서드 , 이렇게 변경이 되어선 안된다 즉 인스턴스매서드를 스태틱매서드로 변경한다거나 반대로 변경해서는 안된다는 것이다.

 

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
public class OrderByThisAndSuper {
    public static void main(String[] args) {
        CC CC = new CC();
        CC.write();
    }
}
class AA{
    int x =10;
    void show(){
        System.out.println("AA의 show() 입니다.");
    }
    void write(){
        show();
        System.out.println(" x= " + x);
    }
}
class BB extends AA{
    int x = 30;
    void show(){
        System.out.println("BB show()");
    }
}
class CC extends BB{
    int x=70;
    void show (){
        System.out.println("CC show()");
    }
}
cs

 

결과는?

CC show()

 x= 10

 

 

4. final - 제어자

 

'마지막의' , '변경될수 없는' 의 의미로 final은 클래스, 매서드 , 멤버변수 , 지역변수에 사용 될수 있다.

클래스에 사용되면 변경될수 없는 클래스 즉 확장 될수 없는 클래스로 다른 클래스의 조상이 될수 없다.

매서드 변경될 수 없는 매서드 즉 오버라이딩 할수 없게된다.

변수에 사용될 경우 값을 변경할 수 없는 상수가 된다.

 

 

5. static - 제어자

 

static은 '공통'의 의미가 있다

인스턴스 변수는 객체 단위로 각기 다르게 할당 되고 관리되어지지만

이 static 멤버변수(클래스 변수)는 인스턴스에 관계 없이 같은 값을 가지게 된다. 이는 JVM의 메모리구조 에서 설명했다. (http://history1994.tistory.com/1?category=668240

 

따라서 메모리구조는 생략하고 코드상으로 설명하자면

static 멤버 변수1. 모든 인스턴스가 공통적으로 사용하며 2. 인스턴스를 생성하지 않고도 사용가능 3. 메모리에 로드되는 시점에 생성 이 된다.

  메서드1.인스턴스를 생성하지 않고도 호출이 가능 2. static 매서드내에서는 인스턴스 멤버들을 직접 사용할 수 없다.(인스턴스 객체를 생성하여 접근 하면 가능) 

 

 

6. this() , super()

 

this()는 자신의 생성자를 호출 하는 것이고 super() 상속관계에 있는 부모 클래스의 생성자를 호출하는것이다. 여기서 주의할 점은

Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자,this() 또는 super()를 호출 해야 한다. 그렇지 않으면 컴파일러는 자동으로 super();를 생성자의 첫줄에 삽입한다.

흔히 착각하는 것이 자식클래스의 생성자에는 무조건 적으로  super() 를 호출 해야 한다고 생각 하는데 그것이 아니라

this() 즉 자신의 또다른 생성자를 호출하지 않는 경우에 + super()를 알맞는 인자로 호출하지도 않는 경우에 자동적으로 super();를 생성하여 호출한다.

 

코드를 통해 보는것이 this() 와 super() 를 이해하기에 좋다

1.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class OrderByThisAndSuper {
 
    public static void main(String[] args) {
 
        SubClass subClass = new SubClass();
        subClass.abc();  //  우선적으로 자식 클래스의 매서드를 참조한다.
        subClass.qwe(); // 없는 경우에는 부모클래스를 참조
    }
}
 
class SuperClass {
 
    public SuperClass(int a) {
        System.out.println("SuperClass : super(int a)");
    }
 
    public void abc() {
        System.out.println("super : abc()");
    }
 
    public void qwe() {
        System.out.println("super : qwe()");
    }
}
 
class SubClass extends SuperClass {
 
    int a = 4;
 
    SubClass() {
 
       this(4); // this() 를 호출 했으므로 super(); 가 자동 생성 되지 않는다.
        System.out.println("sub : SubClass()");
    }
 
    SubClass(int i) {
        super(4);
 
        System.out.println("sub : SubClass(int i)");
 
    }
 
    /*  이 주석을 풀면 이것은 에러가 난다. 왜? this() 와 super() 가 전부 호출되지 않았으므로 super();가 자동으로써진다.
    하지만 부모 클래스에는 인자가없는 생성자가 존재하지 않는다.
    SubClass(char i){
 
    }
    */
    public void abc() {
        super.qwe();
        System.out.println("sub : abc()");
    }
}
cs
SuperClass : super(int a)
sub : SubClass(int i)
sub : SubClass()
super : qwe()
sub : abc()
super : qwe()

 

2.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class OrderByThisAndSuper {
 
    public static void main(String[] args) {
        C c = new C();
        c.start();
    }
}
 
class A {
    int a;
 
    A() {
        a = 10;
    }
 
    void print() {
        System.out.println(a + ",");
    }
}
 
class B extends A {
    int a = 20, b = 30;
 
    B() {
        b = 50;
    }
 
    void print() {
        System.out.println(b + ",");
    }
 
    void bprint() {
        super.print();
    }
}
 
class C extends B {
    int c;
 
    C() {
        c = 60;
    }
 
    void print() {
        System.out.println(c + ",");
    }
 
    void start() {
        print();
        super.bprint();
        System.out.println(super.b);
        System.out.println(a);
 
    }
}
cs

결과는?

60,

10,

50

20

 

2번 과정을 디버깅 해보면 알겠지만 호출에 있어 중요한 순서가 있는데

객체가 생성 된 후   =>   생성자가 호출 됨

즉 객체의 멤버가 초기화 되어진 다음에 이후에 생성자가 호출되어 초기화 된변수를 덮어 쓸수도 있다는 것이다.

그리고 두번째 출력결과 10을 보면 알 수있듯이 호출 매서드에서 멤버변수 출력시 그 메서드가 포함된 클래스에서의 멤버 변수 값(a=10)을 호출한다는것

이것만 주의하면 나머지는 흐름대로 이어진다.

 

 

 

이상으로 자바 공부<2>를 마치겠습니다.

 

 

이 댓글을 비밀 댓글로