ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C# Object Class(조상)+메서드 4종세트, 배열의 조상(System.Array) base, 다형성 (교육 12일차)
    C# 2020. 6. 2. 18:30

    조상 클래스

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

     

    모든 클래스는 기본적으로 object를 상속받는다.

     

    public class DeviceManager == public class DeviceManager : object

     

    object로 시작하면 모든 클래스를 가리킬 수 있다.

    만능 레퍼런스(Object) A는 세개 다 가리킬 수 있다. 그 위에 Object 클래스는 다 가리킬 수 있다. 위의 class A : Object 클래스를 생략해도 결과가 똑같으므로 A클래스 또한 Object 클래스를 상속받은 클래스이다.

    모든 객체라면 Equals, GetHashCode , GetType, ToString 을 가지고 있다. 이 4개는 모든 클래스가 가지고 있다. 가장 최상위 클래스인 Object가 가지고 있는 메서드 항목들이다.

     

    ToString

    ToString 메서드를 호출하면 해당 인스턴스가 속한 클래스의 전체 이름(FQDN)을 반환한다. 

    클래스 A, B, C 가 왼쪽부터 20200602_001 네임스페이스 안, Program 클래스 안에 위치할 때, 중간은 20200602_001네임스페이스 안에 위치 할 때, 오른쪽은 네임스페이스 바깥에 A, B, C 가 위치할 때.

     

    int n = 500;

    Console.WirteLine(n.ToString());

    위의 코드를 작성하게 되면 500이 출력되게 되는데  정수형의 500을 문자형으로 바꾼다.

    숫자 5를 아스키코드표에서 0 의 아스키 코드 48을 더해서 아스키 코드 상의 문자형 5로 바뀐다.

    5 + ' 0 (48)' = '5(53)'

    위 예제와 같은 방법으로 정수형은 문자형으로 변환한다. 우리의 눈에 보이는 500이란 수도 Console.WriteLine이 위와 같은 방식으로 화면에 폰트로 찍어준다.

     

    C#에서 제공되는 기본 타입을 ToString 메서드로 사용할 경우, 그 변수가 가지고 있는 값이 결과로 출력된다. 위 예제에서는, 각각 정수형 실수형 변수가 문자열타입으로 변환되어서 화면에 출력한다. 문자열로 바뀌었으므로 문자열 변수 txt에 정상적으로 대입 가능하다.

     

    GetType

    C#에서는 개발자가 class로 타입을 정의하면 내부적으로 해당 class 타입의 정보를 가지고 있는 System.Type의 인스턴스를 보유하게 되고, 바로 그 인스턴스를 가져올 수 있는 방법이 GetType이다.

     

    GetType()의 반환값은 타입이다. 

    변수나 인스턴스에 대한 타입을 출력한다.

     

    Equals

    Equals메서드는 값을 비교한 결과를 불린형으로 반한다.

    값 형식에 대해서 해당 인스턴스가 소유하고 있는 값을 대상으로 비교하지만 참조 형식에 대해서는 할당된 메모리 위치를 카리키는 식별자의 값이 같은지 비교한다. int 타입은 변수가 가리키는 값 자체를 대상으로 결괏값을 반환한다.

     

    "값 형식"

     

    "참조 형식"

    Equals는 같은 객체인지를 비교한다. 안의 정보는 같지만 다른 객체이다.  book1 객체와 book2는 서로 다른 객체이다.

    하지만 book1이 가리키고 있는 객체의 주소를 book3에도 똑같이 준다면 결과는 True가 된다.

     

    ******************************************************************************************************************************

     

    문자열로 변수를 만들고 초기화를 진행했을 때, 만약 또 다른 문자열 변수로 동일한 문자열을 초기화 할 경우 동일한 주소를 가지는 것을 알 수 있다.

    위의 예제처럼 주소값이 다르지만 True를 리턴한다. 사실 Equals는 String 안에서 다시만들어 놨기 때문에, Object의 Equals를 쓰지 않는다. String전용 Equals를 사용했기 때문에 참이 나온다. 이 경우 객체를 비교하는것이 아니라 안에 있는 글자 자체를 비교한다. 따라서 동일한 결과가 나온다.

     

     

    GetHashCode

    Hash : 1 대 1 대응 (계좌 - 금고), (주민등록번호)

    식별자로 사용, 객체의 고유번호를 알아낼때 사용한다.

     

    Equals메서드와 연계되어 사용되는데, 앞서 Equals메서드는 객체가 같은지를 조사하는데, 이때 해쉬코드가 쓰인다. 따라서 하위 클래스에서 Equals 메서드를 재정의할 때, GetHashCode 메서드도 재정의 해야한다.

     

    HashCode는 4바이트 int값을 반환한다. 값 타입에 대해서는 GetHashCode의 동작 방식을 재정의해서 해당 인스턴스가 동일한 값을 가지고 있다면 같은 해시코드를 반환한다. 

    위의 예제에서는 위의 설명처럼 같은 값을 가지고 있다면 같은 해시코드가 반환됨을 볼 수 있고, 객체에 대해서는 다른 해시코드가 부여되는 것 또한 볼 수 있다. int 자료형 같은 경우, 값이 그대로 해시코드에 적용되는 것도 볼수 있다. 만약 long의 경우 32비트를 넘어버린다. 여기서 GetHashCode를 호출하면 어떤 경우에는 값이 다름에도 동일한 해시 코드가 반환될 수 있다. 다른 코드인데 같은 해시코드가 나오는 것을 해시충돌이라 한다. 

     

    모든 배열의 조상 : System.Array

    Object가 모든 클래스의 조상인 것처럼 배열의 조상은 Array타입을 조상으로 둔다. Object 클래스처럼 C# 컴파일러는 자동적을 int[] 타입을 Array 타입으로부터 상속받는 것으로 처리한다. 이로 인해 배열 인스턴스는 Array 타입이 가진 모든 특징을 자공하는데, 일부 속성 및 메서드는 알아두면 유용하다.

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

     

    this

    실행중인 객체를 가리키는 것이 this이다. 클래스 내부에서 멤버에 접근 했을 때 this를 생략했다고 봐도 무방하다. 이렇게 생각하면 안쓰면 될 것이라고 생각이 든다. 하지만 꼭 필요한 때가 있다. 예를 들어 매개변수와 클래스에 정의된 필드의 이름이 같을 경우 this를 명시함으로써 멤버 변수 isbn을 사용하게 만들 수 있다.

    클래스 이름 옆에 : this (인자, 인자, 인자, 인자) 로 4개의 인자가 들어가는 부분만 일하고 나머진 논다. this를 사용해 또 다른 생성자를 호출하는 구문을 사용함으로써 초기화 관련 코드를 하나의 메서드 내에서 처리하게 했다. 이런 식으로 this를 사용할 수 밖에 없는 전형적인 사례들이 있다. 이를 제외하고 단순히 클래스의 멤버에 접근하기 위해 this를 명시하는 것은 선택의 문제에 불과하다.

     

    this와 인스턴스/정적 멤버의 관계

    객체가 생성되야 사용할 수 있는게 this이다 static멤버에 this쓰면 에러난다, 자세한건 나중에

     

    base

    this 예약어가 클래스 인스턴스 자체를 가리키는 것과는 달리 base 예약어는 부모 클래스를 명시적으로 가리키는데 사용된다. this와 마찬가지로 부모 클래스의 멤버를 사용할 때 base 키워드가 생략된 것과 다름 없다.

    부모찬스

    다른 언어에서는 super

     

    class Book

    {

        decimal isbn13;

        

        public Book(decimal isbn13)

        {

          this.isbn13 = isbn13;

         }

    }

    class EBook : Book

    {

           public EBook()   //에러 발생 (부모 메서드에 인자가 없는 디폴트 메서드가 존재하지 않으므로 에러 발생)

           {

           }

    }

     

    ==> 해결

     부모클래스를 만드는 개발자는 private으로 소유하고 있는 멤버를 초기화 할 수 있지만 자식 클래스는 부모 클래스의 private 멤버에 접근할 수 없으므로 초기화가 불가능하다.

     

    class Book

    {

        decimal isbn13;

        

        public Book(decimal isbn13)

        {

          this.isbn13 = isbn13; //this사용 

         }

    }

    class EBook : Book

    {

           public EBook()  : base(0)

           {

           }

           public EBook(decimal isbn13) : base (isbn13) // 이렇게 값을 연계하는 것도 가능

           {                                                    //부모 메서드로 부터 상속 받은 (isbn)

                   isbn13 = this.isbn13

                   this.isbn13=base.isbn13

            }

    }

     

    내껀 this로 접근 부모 꺼 접근하고 싶으면 this.isbn = base.isbn (부모에서 public)

     

    다형성

    객체 지향의 4대 특징은 추상화, 캡슐화, 상속, 다형성

    오버로딩(Overloading) 오버라이딩(Override)

    오버로딩은 생성자의 이름은 같으나 인자가 다름을 통해서 배웠고, 오버라이딩은 부모클래스가 가진 메서드를 자식클래스가 입맛에 따라 변경하기 위해 사용한다. 부모 클래스가 가진 메서드와 똑같은 이름을 적어주고 안의 내용을 바꿔주면 된다.

     

    위와 같이 부모 메서드에서는 " 이동한다 " 였지만 자식 메서드에서 바꾸고 싶은 메서드를 똑같은 이름을 주고 안의 내용을 바꿔주면 바꾼 내용이 적용된다. 마치 그림위에 새로운 그림을 그리는 것 같은 형태이다.

Designed by Tistory.