반응형

상속(Inheritance)이란?

상속은 한 클래스의 필드(Field)와 메서드(Method)를 다른 클래스로 전달하는 개념이다. 보통 상속하는 클래스를 '부모 클래스', 상속 받는 클래스를 '자식 클래스'라고 한다.

Tenor

 

실생활에 있을 법한 예를 들어 보자. 엄마가 중학생 아들에게 학교 생활을 하며 사용하라고 체크카드를 줬다. 이 체크카드는 엄마 명의의 계좌에 연결되어 있다. 아들은 엄마 명의의 계좌에 있는 돈을 마음대로 사용할 수 있다. 이를 코드로 한 번 구현해 보자.

예시1:

class MotherAccount // base class 부모 클래스  
{
    public string accountName = "신한";
    public void Payment() // 
    {
        Console.WriteLine("0000원이 결제 되었습니다.");
    }
}

class Son : MotherAccount // Son 클래스가 MotherAccount 클래스를 상속  
{
    public string name = "영수";
}

class Program
{
    static void Main(string[] args)
    {
        // mySon 객체 생성  
        Son mySon = new Son();

        // Payment() 메서드 호출
        mySon.Payment();

        Console.WriteLine(mySon.name + "가 " + mySon.accountName + "체크카드를 사용했어요.");
    }
}

예시1의 결과

MotherAccount라는 클래스를 상속한 Son 클래스가 MotherAccount의 멤버에 접근할 수 있게 되었다. 상속을 하는 방법은 클래스를 선언할 때 다음과 같이 : 기호를 사용하면 된다. class Son : MotherAccount

sealed 키워드

다른 클래스가 특정 클래스에 상속되는 것을 원하지 않을 때는 sealed키워드를 선언부 앞에 추가하면 된다.
예시2:

sealed class Vehicle
{

}

class Car : Vehicle{

}

상속하려고 하는 경우 다음과 같은 에러 메시지가 발생할 것이다.

다형성(Polymorphism)이란 무엇일까?

다형성은 "다양한 형태"를 의미하는 말이다. 객체 지향 프로그래밍에서 중요한 개념인데, 같은 이름의 메서드가 다른 클래스에 의해 다르게 구현될 수 있는 능력을 의미한다. 아래 예시를 살펴보자.

예시3:

class Animal  // 부모클래스
{
  public virtual void animalSound() 
  {
    Console.WriteLine("The animal makes a sound");
  }
}

class Pig : Animal  // 자식클래스 Pig
{
  public override void animalSound() 
  {
    Console.WriteLine("The pig says: wee wee");
  }
}

class Dog : Animal  // 자식 클래스 Dog
{
  public override void animalSound() 
  {
    Console.WriteLine("The dog says: bow wow");
  }
}

class Program 
{
  static void Main(string[] args) 
  {
    Animal myAnimal = new Animal();  // Animal 객체 생성
    Animal myPig = new Pig();  // Pig 객체 생성
    Animal myDog = new Dog();  // Dog 객체 생성

    myAnimal.animalSound();
    myPig.animalSound();
    myDog.animalSound();
  }
}

상속을 통해 PigDog 클래스는 Animal 클래스의 특성을 상속받는다. 이처럼 새로운 동물 클래스를 추가할 때 기존 코드의 수정 없이 새로운 클래스를 만들어 확장할 수 있다.

 

앞서 다형성은 같은 이름의 메서드가 다른 클래스에 의해 다르게 구현될 수 있음을 의미한다고 했다. 예시3에서 살펴보면 PigDog 클래스는 Animal 클래스 내의 animalSound()라는 메서드와 동일한 이름을 가진 메서드를 클래스 내에 선언하고 있다.

 

100마리의 동물 클래스를 추가한다고 했을 때 다형성을 사용하지 않는다고 하면 어떻게 될까? animalSound1, animalSound2… 이런 형태로 메서드 이름을 각자 다르게 가져가야 할 것이다.

virtual과 override 키워드

다형성은 virtual 키워드와 override 키워드를 사용해 구현할 수 있다.

예시4:

class Animal  // 부모클래스
{
  public virtual void animalSound() 
  {
    Console.WriteLine("The animal makes a sound");
  }
}

부모 클래스에서 virtual 키워드가 붙은 메서드는 하위 클래스에서 재정의 할 수 있게 된다.

class Dog : Animal  // 자식 클래스 Dog
{
  public override void animalSound() 
  {
    Console.WriteLine("The dog says: bow wow");
  }
}

Dog 클래스 내의 animalSound()메서드는 Animal 클래스 내의 메서드와 이름이 같다. 하지만 메서드 내의 코드는 다르게 작성된 것을 확인할 수 있다. 이런 형태로 부모 클래스의 메서드를 재정의(Override) 할 수 있다.

반응형
반응형

프로퍼티 및 캡슐화(Property and Encapsulation)

캡슐화(Encapsulation)

객체 지향 프로그래밍의 주요 개념 중 하나이다. 데이터와 그 데이터를 조작하는 메서드를 하나로 묶어 “민감한” 데이터가 사용자에게 숨겨지도록 하는 것이다.

이전 포스트에서 접근 제한자의 사용 방법에 대해 다뤘다. private라는 접근 제한자를 사용함으로써 외부 클래스에서 접근을 제한했는데, 이와 같은 일련의 과정을 캡슐화(Encapsulation)라고 할 수 있을 것이다.

캡슐화는 다음과 같은 과정을 수행해야 한다.

  • 필드/변수를 private로 선언
  • private 필드에 액세스하고, 업데이트하기 위해 get, set 메소드를 사용

프로퍼티(Property)

앞서 설명한 거처럼 private는 동일한 클래스 내에서만 접근할 수 있다. 유니티로 개발을 하다 보면 때때로 외부 클래스에서 private 멤버에 접근해야 하는 경우가 있다. 이 것은 프로퍼티 통해 가능하다.

프로퍼티는 get, set 두 가지 메서드를 사용해 public으로 선언했을 때처럼 private 필드의 값을 읽고, 쓰고, 계산하는 멤버다. 멤버는 클래스 내에 있는 변수, 메서드 등을 멤버라고 한다.

예시 1:

class Person
{
  private string name; // 필드

  public string Name   // property
  {
    get { return name; }   // get 메소드
    set { name = value; }  // set 메소드
  }
}

Name 프로퍼티는 name 필드와 연결된다. 프로퍼티의 첫 글자는 대문자이고, 필드와 프로퍼티의 이름은 같게 하는 것이 권장된다.

get 메서드는 name 필드의 값을 반환한다. set 메소드는 name 필드에 값을 할당한다. 예시 1에서 value 키워드는 name 필드에 할당하는 값을 의미한다. 예시 2에서 조금 더 자세히 살펴보도록 하자.

예시 2:

class Person
{
  private string name; // 필드
  public string Name   // 프로퍼티
  {
    get { return name; }
    set { name = value; }
  }
}

class Program
{
  static void Main(string[] args)
  {
    Person myObj = new Person(); // 객체 생성
    myObj.Name = "Liam";
    Console.WriteLine(myObj.Name);
  }
}

//출력 : Liam

Program이라는 외부 클래스에서 Person 클래스에 대한 myObj라는 객체를 생성했다. 그리고 myObj객체에 Name 프로퍼티를 사용하여 name이라는 필드에 Liam이라는 값을 할당했다.

프로퍼티를 사용했기 때문에 private로 선언되었지만 외부 클래스에서 접근하여 필드의 값까지 수정할 수 있게 된 것이다.

자동 프로퍼티(Automatic Property)

C#에서는 단축/자동 프로퍼티를 사용하는 방법도 제공한다. 속성에 대한 필드를 정의할 필요가 없는 경우에는 예시 3에서 보는 것처럼 단축해서 코드를 작성할 수 있다.

예시 3:

class Person
{
  public string Name  // 프로퍼티
  { get; set; }
}

class Program
{
  static void Main(string[] args)
  {
    Person myObj = new Person();
    myObj.Name = "Liam";
    Console.WriteLine(myObj.Name);
  }
}

//출력 Liam

예시 2예시 3은 기능적으로는 동일하다고 불 수 있다. 그러나 내부적으로는 다르게 구현되어 있다. 예시 2에서는 name필드에 Liam이라는 값을 할당하지만, 예시 3에서는 백킹 필드(Backing Filed)라는 비공개 변수에 값이 할당된다.

백킹 필드는 프로퍼티에 의해 읽거나 쓰이는 실제 데이터를 저장하는 데 사용되는 비공개 변수다. 프로퍼티의 내부에서만 사용되며, 클래스 외부에서는 백킹 필드로 직접적으로 접근할 수는 없다.

그렇다면 여러 객체를 생성하는 경우에는 어떻게 될까? 당연하게도 객체마다 프로퍼티를 사용했을 때 각각의 백킹 필드가 할당된다.

부가적으로 설명하자면 객체를 생성하면 컴퓨터 메모리에 객체의 데이터와 메서드를 저장하기 위한 메모리 블록이 할당된다. 이 메모리 블록 내에서 객체와 관련된 모든 멤버에 대한 메모리가 할당되는 것이고, 고유 주소를 갖게 된다. 백킹 필드 객체가 할당받은 메모리 블록 내에 데이터를 저장하는 것이다.

총정리

캡슐화와 프로퍼티는 객체 지향 프로그래밍에서 코드의 가독성, 유지 보수성, 재사용성, 보안 등을 향상하는데 중요한 역할을 한다.

캡슐화로 외부에서 민감한 데이터에 접근하는 것을 막음과 동시에, 개발자가 프로퍼티를 통해 접근할 수 있게 한다.

반응형
반응형

접근 제한자(Access Modifier)란 무엇인가?

우리나라에서는 접근 제한자 또는 접근 한정자라고 부르는 거 같다. 정리해 보자면 접근 제한자는 클래스, 필드, 메소드 및 속성에 대한 접근 수준을 설정하는 데 사용된다. 아래 예시를 살펴보자.

예시1:

public string color;

예시1에서 public을 접근 제한자라고 한다. 가장 앞

C#의 접근 제한자

접근 제한자 설명
public 외부 클래스를 포함한 모든 클래스에서 접근을 허용함.
private 동일한 클래스 내에서만 접근을 허용함.
protected 동일한 클래스 내에서 또는 해당 클래스에서 상속된 클래스에서 접근을 허용함.
internal 자체 어셈블리 내에서만 접근을 허용함. 다른 어셈블리에서는 없음.

 

private protectedprotected internal처럼 조합하여 사용하는 경우도 있다. protectedinternal에 대해서는 나도 사용해 본 적이 없다. 추후에 다루게 된다면 다시 한번 정리해 보도록 하겠다.

Private Modifier(비공개 제한자)

private를 사용하여 필드를 선언하면 동일한 클래스 내에서만 접근할 수 있다.

예시2:

class Car
{
        private string model = "Mustang";

      static void Main(string[] args)
    {
            Car myObj = new Car();
        Console.WriteLine(myObj.model);
    }
}

// 출력 : Mustang

예시3:

class Car
{
  private string model = "Mustang";
}

class Program
{
  static void Main(string[] args)
  {
    Car myObj = new Car();
    Console.WriteLine(myObj.model);
  }
}

model 변수는 Car 클래스 내부에서 private로 선언되었다. 그런데 Program 클래스에서 접근을 하려고 하는 경우 다음과 같은 에러가 발생한다.

private를 사용했기 때문에 외부 클래스에서 접근할 수 없다.

접근 제한자를 사용하여 클래스와 멤버의 접근을 제어함으로써 코드의 안정성을 높일 수 있다.

반응형

+ Recent posts