객체지향 - 클래스 상속 (class inheritance)
사람, 물고기, 새.
이 세가지 대상들을 구현하고 싶을 때
상속을 사용하지 않는다면 이렇게 구현할 수 있을 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Human
{
void Eat() { }
void Move() { }
void Think() {
}
class Fish
{
void Eat() { }
void Move() { }
}
class Bird
{
void Eat() { }
void Move() { }
}
|
그런데 겹치는 부분이 보인다.
중복되는 코드는 적을수록 좋다.
따라서 상속을 사용해 중복되는 코드를 없애보자.
상속이 무엇인지 잘 모르겠다면 재산 상속을 떠올려 보자.
다만 객체지향에서의 상속은 재산 상속이 아니라 멤버 상속이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class Life
{
void Eat() { Console.WriteLine("먹는다."); }
void Move() { Console.WriteLine("움직인다."); }
}
class Human : Life
{
void Think() { }
}
class Fish : Life
{
}
class Bird : Life
{
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
부모 클래스 Life를 정의하고, 각 클래스마다 Life 클래스를 상속시켜 주었다.
다만 이렇게 하면 부모 클래스의 멤버의 접근 제한자가 private이므로 자식 클래스에서의 접근이 불가능하다.
private으로 명시해도 되지만, 정보 은닉을 위한 protected라는 접근 제한자도 있다.
protected는 자식 클래스에서의 접근까지만 허용한다.
아래 예제에서는 public으로 명시했다.
그런 경우 이렇게 부모 메서드를 자신 인스턴스가 바로 사용할 수 있다.
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
|
using System;
namespace example2
{
class Program
{
static void Main(string[] args)
{
Human human = new Human();
Fish fish = new Fish();
human.Eat();
fish.Move();
}
}
class Life
{
public void Eat() { Console.WriteLine("먹는다."); }
public void Move() { Console.WriteLine("움직인다."); }
}
class Human : Life
{
void Think() { }
}
class Fish : Life
{
}
class Bird : Life
{
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
출력 결과 :
먹는다.
움직인다.
계속하려면 아무 키나 누르십시오 . . .
클래스의 상속을 막고 싶은 경우 sealed 예약어를 추가하면 된다.
그러면 상속을 시도할 경우 오류가 뜬다.
계층 상속, 다중 상속
c#에서는 계층 상속은 지원하지만 다중 상속은 지원하지 않는다.
즉 어떤 부모의 자식 클래스가 다른 클래스의 부모가 되는 것은 가능하지만,
동시에 두 클래스를 부모로 둘 수는 없다.
class Ancestor
{
}
class Parent : Ancestor
{
}
class Child : Parent // 계층 상속. 문제 없음
{
}
class Ancestor
{
}
class Parent
{
}
class Child : Ancestor, Parent // 다중 상속. 컴파일 오류
{
}
Object 클래스
클래스를 정의할 때 어떠한 부모 클래스도 상속시키지 않는다면,
c# 컴파일러가 그 클래스에 Object 클래스를 상속시킨다.
c#은 계층 상속이 가능하므로 부모 클래스가 따로 있는 자식 클래스들도 결국 위로 올라가다 보면 object 클래스를 조상으로 가지게 된다.
따라서 c#의 모든 클래스는 Object 클래스를 상속받는다.
클래스를 상속 받으므로 모든 클래스는 Object 클래스에 정의된 메서드들을 사용할 수 있을 것이다.
Object 클래스에 대한 자세한 설명은 MSDN을 참고하자
: https://docs.microsoft.com/ko-kr/dotnet/api/system.object?view=netframework-4.8#------
Object 클래스에 정의된 메서드들 중 가장 유명한 것이 ToString() 메서드이다.
이 메서드는 접근 제한자가 public이기 때문에 인스턴스.ToString() 과 같이 사용할 수 있는 것이다.
Array 클래스
Object 클래스가 모든 타입의 조상인 것처럼, Array 클래스는 모든 배열의 조상이다.
int[ ] intArray = new int { 0, 1, 2, 3 };
여기에서 int[ ] 타입은 Array 타입을 상속 받는다.
따라서 Array 클래스에 정의된 메서드를 사용할 수 있다.
Array 클래스 역시 MSDN에 상세한 설명이 나와 있다.
: https://docs.microsoft.com/ko-kr/dotnet/api/system.array?view=netframework-4.8
생성자에서 나타나는 오류
자식 클래스의 생성자를 호출하면 부모 클래스의 생성자도 같이 호출된다.
따라서 부모 클래스에 매개변수를 필요로 하는 생성자가 정의된 경우 오류가 발생할 수 있다.
Life 클래스에 매개변수를 갖는 생성자를 추가해보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Life
{
string name;
public Life(string name)
{
this.name = name;
}
public void Eat() { Console.WriteLine("먹는다."); }
public void Move() { Console.WriteLine("움직인다."); }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
그렇게 하면 상속하는 부분에서 이렇게 오류가 뜬다.
자식 클래스의 생성자를 호출할 때 부모 클래스의 생성자가 호출되는데,
그때 매개변수로 어떤 값을 넘길지 정해지지 않았기 때문이다.
이는 자식 클래스의 생성자를 만들 때 부모 클래스의 생성자를 명시함으로써 해결할 수 있다.
Human 클래스를 다음과 같이 수정해보자.
1
2
3
4
5
6
7
8
9
10
|
class Human : Life
{
public Human(string name) : base(name)
{
}
void Think() { }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
(base는 부모 클래스를 가리키는 키워드이다.)
이제 Human의 인스턴스를 생성하고 name을 출력해보자.
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
|
using System;
namespace example2
{
class Program
{
static void Main(string[] args)
{
Human human = new Human("사람");
}
}
class Life
{
public string name;
public Life(string name)
{
this.name = name;
}
public void Eat() { Console.WriteLine("먹는다."); }
public void Move() { Console.WriteLine("움직인다."); }
}
class Human : Life
{
public Human(string name) : base(name)
{
}
void Think() { }
}
class Fish : Life
{
public Fish(string name) : base(name)
{
}
}
class Bird : Life
{
public Bird(string name) : base(name)
{
}
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
출력 결과 :
사람
계속하려면 아무 키나 누르십시오 . . .
'C#' 카테고리의 다른 글
[C# / 객체지향] 8. 다형성 - 오버로드 (Method Overload) (0) | 2020.01.08 |
---|---|
[C# / 객체지향] 8. 다형성 - 메서드 오버라이드 (Method Override) (0) | 2019.12.19 |
[C# / 객체지향] 6. 캡슐화와 정보 은닉 (0) | 2019.12.16 |
[C# / 객체지향] 5. 네임스페이스(namespace) (0) | 2019.12.15 |
[C# / 객체지향] 4. 정적(Static) 멤버 (0) | 2019.12.14 |