본문으로 바로가기

C# 수업#10

category C# 2020. 6. 2. 14:14

안녕하세요~! 문쑹입니다 :)

 

모든 타입의 조상 : System.Object

클래스를 정의할 때 부모 클래스를 명시하지 않는다면 C# 컴파일러는 기본적으로 object라는 타입에서 상속받는다고 가정하고 자동으로 코드를 생성한다.

public class DeviceManager

{

}

//또는

public class DeviceManager : object

{

}

그런데 부모 클래스를 지정하더라도 그 부모 클래스는 어떤 클래스를 다시 상속받았을 것이고 결국에는 최초의 클래스가 object 타입을 상속받는 것으로 끝난다. 결국 C#에서 정의되는 모든 클래스의 부모는 object가 된다.

저번 강의에서 살펴본 Computer, Notebook, Desktop, Netbook, Devicemanager 클래스의 상속 관계를 정리하였다.

 

Object를 사용하면 모든 것을 가리킬 수 있다. Object는 그 자체가 참조형임에도 값 형식의 부모 타입이기도 하다.

Object는 그 자체가 참조형임에도 값 형식의 부모 타입이기도 한다. 참조 형식과 값 형식은 처리 방식이 매우 다른데, 이러한 불일치를 구분하기 위해 닷넷에서는 모든 값 형식을 System.ValueType 타입에서 상속받게 하고 있으며, 다시 System.ValueType은 object를 상속 받고 있다. 값 형식은 System.ValueType으로부터 상속받은 모든 타입을 의미하고, 참조 형식은 object로부터 상속받은 타입 가운데 System.ValueType의 하위 타입을 제외한 모든 타입을 의미한다. 아래의 그림은 정리된 다이어 그램이다.

Object로부터 파생된 타입 관계

C#에서 정의되는 모든 형식은 Object로 변환하고 다시 되돌리는 것이 가능하다. Object는 4개의 public 메서드를 포함하고 있다.

public class Object

{

    public virtual bool Equals(object obj);

    public virtual int GetHashCode();

    public Type GetType();

    public virtual string ToString();

}

 

ToString() 메서드

위쪽에서 언급 했듯이, C#의 모든 클래스 구조체는 Object 클래스를 암시적으로 상속합니다. 따라서 C#의 모든 개체는 해당 개체의 문자열을 반환하는 ToString() 메서드를 가져옵니다. 예를들어, 정수형, 실수형 등을 문자열로 변환하여 출력해줍니다. 아래의 예제를 살펴보겟습니다.

정수 int n, doulbe형, string형 3가지의 변수가 있습니다. txt(문자형) + n.ToString()을 했는데 여기서 정수형 n을 ToString()메서드를 사용하여 정수형 500을 문자열 "500"으로 변형해주었다.

 

GetType() 메서드

class로 타입을 정의하면 내부적으로 해당 class 타입의 정보를 가지고 있는 System.Type의 인스턴스를 보유하게 되고, 바로 그 인스턴스를 가져올 수 있는 방법이 GetType() 메서드를 통해 제공된다.

Computer class는 앞전에 만들었던 class를 사용하였습니다.

 

ToString 메서드가 하위 클래스에서 재정의되면 타입의 전체 이름이 아닌 값 자체를 문자열로 반환한다. GetType 메서드는 그러한 클래스에 대해 타입의 전체 이름을 반환하는 수단을 제공한다.

 

GetType은  "클래스의 인스턴스"로부터 Type을 구하지만 "클래스의 이름"에서 곧바로 Type을 구하는 방법도 제공되는데 이때는 typeof라는 예약어를 사용해야 한다.

Equals 메서드

Equals 메서드는 값을 비교한 결과를 불린형(boolean)으로 반환한다. 즉, True 와 False로만 값을 출력한다.

위의 예제를 보면 n1과 n2의 각각 5라는 정수형 값을 주었다. Equals() 메서드로 n1과 n2를 비교하였을 때 값이 같아서 True가 나오는 것을 볼 수 있다. 하지만 n2에 6을 대입한 후 다시 한 번 Equals() 메서드로 비교한 결과 False가 나오는 것을 확인 하였다.

하지만 class로 생성한 참조 형식의 값은 False로 나오는데 이유는 동일한 값을 소유한 참조 형식에 대해서 Equals 메서드는 False를 반환한다. 왜냐하면 "힙에 할당된 데이터 주소를 가리키고 있는 스택 변수의 값"을 비교하기 때문이다.

new Book으로 생성된 힙 메모리의 위치가 다르기 때문에 그 안에 들어간 값이 어떤 것인지는 상관없이 Equals 메서드는 False를 반환하게 된다.

 

GetHashCode

Hash는 1:1 대응을 뜻 한다. GetHashCode 메서드는 특정 인스턴스를 고유하게 식별할 수 있는 4바이트 int 값을 반환한다. GetHashCode가 Equals 메서드와 연계되는 특성이 있다. 

*출력 결과는 사용자가 위의 코드를 어떤 버전의 닷넷 프레임워크에서 실행했느냐에 따라 달라질 수 있다. GetHashCode의 반환값은 닷넷 프레임워크의 내부 구현이 바뀌면 언제든지 바뀔 수 있다는 점이다.

 

모든 배열의 조상 : System.Array

object가 모든 타입의 조상인 것처럼 소스코드에 정의되는 배열은 모두 Array 타입을 조상으로 둔다.

int [] intArray = new int [] {0, 1, 2, 3, 4, 5 };

C# 컴파일러는 자동적으로 int[] 타입을 Array 타입으로부터 상속받는 것으로 처리한다. 배열 인스턴스는 Array 타입이 가진 모든 특징을 제공한다.

 

Array 타입의 멤버

멤버 타입 설명
Rank 인스턴스 프로터피 배열 인스턴스의 차원(dimension) 수를 반환한다.
Length 인스턴스 프로터피 배열 인스턴스의 요소(element) 수를 반환한다.
Sort 정적 메서드 배열 요소를 값의 순서대로 정렬한다.
GetValue 인스턴스 메서드 지정된 인덱스의 배열 요소 값을 반환한다.
Copy 정적 메서드 배열의 내용을 다른 배열에 복사한다.

Array 멤버를 사용한 예제이다.

배열이 System.Array로부터 상속받은 참조형 타입이다.

 

this 메서드

객체는 외부에서 자신을 식별할 수 있는 변수를 갖는다.

Book book = new Book(9788998139018);

변수 book은 마침표를 사용해 객체의 멤버를 호출할 수 있는데, 클래스 내부의 코드에서 객체 자신을 가리킬수 있는 목적으로 사용되는 것this입니다.

this를 사용하여 또 다른 생성자를 호출하는 구문을 사용함으로써 초기화 관련 코드를 하나의 메서드 내에서 처리할 수 있게 되었다.

 

이 코드를 컴파일하면 public EBook 생성자 정의에서 오류가 발생하는 것을 볼 수 있다. 자식 클래스를 생성한다는 것은 곧 부모 클래스의 생성자도 함께 호출한다는 의미이기 때문입니다. 부모 클래스를 만드는 개발자는 private으로 소유하고 있는 멤버를 초기화할 수 있지만 자식 클래스는 부모 클래스의 private 멤버에 접근할 수 없으므로 초기화가 불가능하다. 이 예제에서 오류가 나는 이유는 자식 클래스가 생성되는 시점에 부모 클래스의 생성자를 호출해야 하는데 "기본 생성자"가 부모 클래스에는 없기 때문이다.

생성자는 그것이 정의된 클래스 내부의 필드를 초기화하는 일만 담당하면 되고, 부모 클래스의 필드는 부모 클래스의 생성자가 초기화할 것이므로 맡겨버리면 된다. 이런 에러가 발생하였을때 base예약어를 이용해 어떤 생성자를 어떤 값으로 호출해야 할지 명시해서 문제를 해결할 수 있다.

 

다형성

객체지향의 4대 특징은 일반적으로 추상화, 캡슐화, 상속, 다형성을 말한다. 객체지향 언어에서 보통 추상화는 "클래스"를 통해 제공되기 때문에 일전에 배운 것들이 추상화를 배운 것이라고도 할 수 있다. 캡슐화 또는 상속도 예제들을 통해서 다뤘다. 다형성이 남았는데 문자 그대로 해석해서 "여러 가지 형태"를 띤다는 것이다.

 

메서드 오버라이드

메서드 오버라이드 부분은 다음 강의에서 이어서 다루겠습니다.

이상 포스팅을 마치겠습니다. 감사합니다 :)

Hasta Luego~!

'C#' 카테고리의 다른 글

C# 수업#12  (0) 2020.06.04
C# 수업#11  (0) 2020.06.03
C# 수업#9  (0) 2020.06.01
C# 수업#8  (0) 2020.05.29
C# 수업#7  (0) 2020.05.28