본문 바로가기

2021/java

java - 상속

1. 상속의 개념

어떠한 class 내의 멤버들을 확장(상속)해서 다른 class가 갖도록 하는 것.

 

Cal라는 클래스를 수정할 수 없는 상황에서 이 클래스에 minus라는 새로운 메소드를 추가해야 하는 경우,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Cal{
    public int sum(int v1, int v2) {
        return v1 + v2;
    }
}
 
class Cal2{
    public int sum(int v1, int v2) {
        return v1 + v2;
    }
    public int minus(int v1, int v2) {
        return v1 - v2;
    }
}
cs

위와 같이 상속을 사용하지 않고 새로운 class를 생성하여 사용한다면

 - 코드 중복으로 인한 비효율성의 문제

 - Cal2 내의 sum이라는 메소드가 Cal과 관련이 있음을 알아보기 어렵다는 가독성의 문제

 - Cal 내의 멤버가 수정 혹은 삭제될 경우 Cal2에는 그 내용이 반영되지 않는다는 문제

등이 발생한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Cal{
    public int sum(int v1, int v2) {
        return v1 + v2;
    }
}
 
class Cal3 extends Cal {
    public int minus(int v1, int v2) {
        return v1 - v2;
    }
}
 
public class InheritanceApp {
 
    public static void main(String[] args) {
        Cal3 c3 = new Cal3();
        System.out.println(c3.sum(73)); // 10
        System.out.println(c3.minus(73)); // 4
    }
}
cs

이러한 문제들을 개선하기 위해 위와 같이 extends라는 키워드를 사용해 클래스를 상속하여 사용할 수 있다.

 

2. overriding

 1) overridding의 개념

java에서는 어떤 class내의 변수나 메소드가 호출되면, 해당 class에 그 변수나 메소드가 존재하는지 우선적으로 확인한다. 존재하면 그 명령을 실행하고, 존재하지 않으면 해당 클래스가 상속받은 부모 클래스를 확인한다.

따라서 부모 클래스 내에 있는 변수나 메소드의 내용을 그대로 상속받지 않고 새롭게 정의하여 사용하고자 한다면, 자식 클래스에 해당 변수나 메소드와 똑같은 이름으로 변수나 메소드를 재정의하면 된다.

이렇게 재정의하는 것을 overriding 이라고 한다.

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
class Cal{
    public int sum(int v1, int v2) {
        return v1 + v2;
    }
}
 
class Cal3 extends Cal {
    public int minus(int v1, int v2) {
        return v1 - v2;
    }
    public int sum(int v1, int v2) {
        System.out.println("test");
        return v1 + v2;
   } // overriding
}
 
public class InheritanceApp {
 
    public static void main(String[] args) {
 
        Cal3 c3 = new Cal3();
        System.out.println(c3.sum(73));
 
    }
}
cs

위 코드의 main 메소드에서 sum이라는 메소드를 호출하고 있는데, 이 메소드는 Cal과 Cal3에 모두 정의되어 있다.

이때 java에서는 자식 클래스인 Cal3을 먼저 확인하기 때문에 Cal이 아닌 Cal3 내 메소드의 내용이 실행된다.

 

 2) overriding vs overloading

overloading은 클래스 내에 존재하는 메소드와 동일한 이름의 메소드를 정의하되, 그 형태를 다르게 하여 클래스 내에 과적하는 것이다. overriding과 용어가 비슷하여 헷갈릴 수 있지만 overloading은 상속과는 직접적인 관련이 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Cal{
    public int sum(int v1, int v2) {
        return v1 + v2;
    }
 
    // overloading
    public int sum(int v1, int v2, int v3) {
        return v1 + v2 + v3;
    }
    // 앞에서 정의했던 sum이라는 메소드와 이름이 같지만 (매개변수의) 형태는 다른 새로운 메소드를 정의.
}
 
public class InheritanceApp {
 
    public static void main(String[] args) {
        Cal c = new Cal();
        System.out.println(c.sum(21));
        System.out.println(c.sum(215));
        // 주어지는 인자의 형태가 다르므로 서로 다른 메소드가 호출됨.
        
    }
}
 
cs

 

3. this와 super

  super는 자신의 부모, this는 자기 자신을 나타내는 키워드이다.

 

  1) super

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Cal{
    public int sum(int v1, int v2) {
        return v1 + v2;
    }
}
 
class Cal3 extends Cal {
    public int sum(int v1, int v2) {
        System.out.println("test");
        return super.sum(v1, v2);
    } 
}
 
public class InheritanceApp {
    public static void main(String[] args) {
        Cal3 c3 = new Cal3();
        System.out.println(c3.sum(73));
/*
test
10
*/
    }
}
cs

위 코드에서는 Cal 내의 sum이라는 메소드를 자식 클래스인 Cal3에서 overriding하되, 부모 클래스 내 sum 메소드의 내용 또한 일부 계승하고자 한다. 이를 위해 super라는 키워드를 사용하여 부모 클래스에 있는 sum을 호출하였다.

 

  2) this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Cal{
    public int sum(int v1, int v2) {
        return v1 + v2;
    }
    
    // overloading
    public int sum(int v1, int v2, int v3) {
        return this.sum(v1, v2) + v3;
    }
}
 
public class InheritanceApp {
    public static void main(String[] args) {
        Cal c = new Cal();
        System.out.println(c.sum(735)); // 15
    }
}


cs

위 코드에서 Cal이라는 클래스에는 sum이라는 메소드가 overloading되어 있는데, 이때 이미 앞에서 정의한 sum 메소드의 리턴 값을 활용하고자 한다. 이를 위해 this를 사용하여 자기 자신인 Cal 내의 sum 메소드를 호출하였다.

 

4. 상속과 생성자

   java에서는 부모 클래스가 생성자가 있다면 자식 클래스는 반드시 부모의 생성자를 실행시키도록 강제하고 있다.

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
class Cal{
    int v1, v2;
 
    public Cal(int v1, int v2) {
        System.out.println("Cal init!!");
        this.v1 = v1;
        this.v2 = v2;
    } // 부모 생성자
 
    public int sum() {
        return this.v1 + this.v2;
    }
 
}
 
class Cal3 extends Cal {
    public Cal3(int v1, int v2) {
        super(v1, v2); // 부모 생성자 실행.
        System.out.println("Cal3 init!!");
    }    
 
    public int minus() {
        return this.v1 - this.v2;
    }
}
 
public class InheritanceApp {
    public static void main(String[] args) {
        Cal c = new Cal(21);
        Cal3 c3 = new Cal3(21);
 
        System.out.println(c3.sum()); // 3
        System.out.println(c3.minus()); // 1
    }
}
cs

'2021 > java' 카테고리의 다른 글

java - 객체 지향 프로그래밍  (0) 2021.08.02
백준 2501 - 약수 구하기  (0) 2021.07.14
백준 1000 - A+B  (0) 2021.07.14