클래스란?

상태
완료
담당자
날짜
숫자
0

클래스란?

여러분. 객체지향 프로그래밍에서 클래스가 무엇인지 정확히 알고 계시나요? 저는 클래스와 관련된 개념들에 대해 막연히는 알고 있었지만 정확히 이해하지는 못하며 코드로 써보기에만 급급했던 것 같습니다.
이번에는 객체지향 프로그래밍에서 중요한 개념인 클래스의 개념에 대해 정확히 알아보고 더 나아가 그에 연관된 개념들인 상속, 오버라이딩, 오버로딩에 대해서도 알아보도록 하겠습니다.

클래스란 무엇인가?

클래스란 ‘관련된 속성과 메서드를 묶어서 객체를 생성하기 위한 템플릿’ 입니다.
여기서 중요한 키워드는 ‘속성’ , ’메서드’ , ’객체’ 라고 할 수 있습니다. 그렇다면 속성과 메서드, 객체란 무엇인지 알아봅시다.

속성이란?

속성은 객체 안에 속한 변수 또는 값 입니다. 여러분이 사람이라는 객체를 만든다면 그 안에는 이름, 나이, 성별 등의 속성이 있을 것입니다. 이처럼 속성이란 그 객체를 구성하는 요소라고 할 수 있습니다.

메서드란?

메서드는 특정 클래스나 객체의 행동을 정의하는 함수적인 개념을 의미합니다. 예를 들어 여러분이 사람이라는 객체를 만들었을 때, 밥을 먹는 동작, 잠을 자는 동작, 옷을 입는 동작 등을 수행하게끔 할 수 있겠죠. 이처럼 메서드는 객체의 동작과 기능을 정의합니다.

객체란?

객체란 프로그래밍에서 속성과 기능을 가진 독립적인 데이터 단위 입니다. 여기서 독립적인 데이터 단위라는 말의 의미가 무엇인지 이해가 안 되실 수 있는데요. 각 객체는 다른 객체와 분리된 상태를 유지하고 이는 자신만의 상태와 동작을 관리할 수 있음을 의미합니다. 그렇다면 객체는 왜 사용하는 걸까요?
객체를 사용하는 이유는 데이터와 그 데이터 관련 연산을 묶어 관리하기 위해서 입니다. 이는 즉, 클래스를 사용하는 이유와 직결됩니다.

클래스를 사용하는 이유?

클래스란 ‘관련된 속성과 메서드를 묶어서 객체를 생성하기 위한 템플릿’ 이라고 했습니다.
그렇다면 클래스를 사용하는 이유는 단순히 ‘객체를 생성하기 위해서인가?’ 라고 생각하실 수 있는데, 객체를 생성하기 위해 클래스를 사용하는 것은 맞지만 결국 클래스를 사용하여 객체를 생성하는 궁극적 이유는 코드를 직관적으로 볼 수 있게 하고, 재사용성과 유지보수에 용이하게 하기 위해서입니다.
즉, 클래스에서 데이터와 그 데이터 관련 연산을 묶어 관리하기 위한 객체를 생성함으로써 코드의 가독성과 재사용성을 높이고, 유지보수에 용이하게 하기 위해 우리는 클래스를 사용하는 것입니다.

클래스의 상속

지금까지 클래스란 무엇이고 이를 사용하는 이유 등에 대해 알아보았습니다.
하지만 클래스를 사용하는 이유를 정확히 이해하기 위해서는 클래스의 상속에 대해 알아야합니다. 그렇다면 상속이란 무엇인지 알아보겠습니다.
상속 : 특정 기능(데이터 및 동작)을 제공하는 기본 클래스(부모 클래스)를 정의하고 해당 기능을 상속하거나 재정의하는 파생 클래스(자식 클래스)를 정의할 수 있는 객체 지향 프로그래밍 언어의 기능
우리가 보통 알고 있는 상속이라하면, 부모의 유산을 자식이 넘겨받게 되는 개념을 생각할 텐데요.
하지만 프로그래밍 언어에서의 상속은 조금 다릅니다. 자식 클래스가 부모 클래스의 속성이나 기능을 넘겨받긴 하지만 부모 클래스의 속성이나 기능이 사라지진 않거든요.
메서드에서 예를 들었듯이, 사람이라는 객체를 만들었고, 그 객체의 메서드에는 밥을 먹는 동작, 잠을 자는 동작, 옷을 입는 동작이 있다고 가정합시다. 여러분이 그 이후에 코딩하는 사람이라는 객체를 만드려고 할 때, 코딩하기 라는 동작만 추가하면 되는데, 사람이라는 객체의 동작을 다시 정의하기엔 너무 귀찮겠죠? 그럴 때, 상속이라는 개념을 이용하면 쉽게 해결할 수 있습니다.
public class Person { public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } public Person(string name, int age, string gender) { Name = name; Age = age; Gender = gender; } public void Eat() { Console.WriteLine($"{Name}이(가) 밥을 먹고 있습니다."); } public void Sleep() { Console.WriteLine($"{Name}이(가) 잠을 자고 있습니다."); } public void Dress() { Console.WriteLine($"{Name}이(가) 옷을 입고 있습니다."); } }
C#
복사
위의 코드는 이름, 나이, 성별이라는 속성을 가지고 밥 먹기, 잠 자기, 옷 입기라는 메서드를 가진 Person이라는 객체입니다. 위의 예시를 상속받아 코딩하는 Coder라는 객체를 만들어보겠습니다.
public class Coder : Person // 상속 키워드 = ':' { public Coder(string name, int age, string gender) : base(name, age, gender) { } public void Code() { Console.WriteLine($"{Name}이(가) 코딩을 하고 있습니다."); } }
C#
복사
이런 식으로 Coder라는 객체는 Person의 객체를 상속받고 코딩하기 라는 메서드만 추가되었습니다. Coder라는 객체는 결국 Person과 같이 이름, 나이, 성별이라는 속성을 가지고, 밥 먹기, 잠 자기, 옷 입기라는 메서드를 가지며, 코딩하기라는 메서드만 추가되었습니다.

오버라이딩이란?

위에서 알아본 상속을 통해 부모 클래스의 속성과 기능을 물려받는 자식 클래스를 생성하는 것을 알아보았습니다.
그런데 여러분이 Coder라는 객체를 만들었을 때, Coder의 기능을 재정의하고 싶을 수 있습니다. 예를 들어, Person(부모 클래스)의 기능인 밥 먹기, 잠 자기, 옷 입기라는 기능이 있을 때, 이를 Coder(자식 클래스)가 변형하여 밥 먹기를 코딩하면서 밥 먹기, 코딩하다가 잠에 들기, 편한 옷을 입고 코딩하기 라는 기능으로 바꾸고 싶을 수 있습니다. 그럴 때는 오버라이딩을 사용하여 메서드를 재정의해주면 됩니다.
오버라이딩이란 부모-자식 상속 관계에 있는 클래스에서 상위 클래스의 메서드를 하위 클래스에서 재정의하는 것을 말합니다.
일단 메서드 오버라이딩을 하기 위해서는 먼저, 부모 클래스의 메서드를 가상 메서드(virtual method)로 선언하고, 자식 클래스에서 해당 메서드를 오버라이딩(override)해야합니다.
코드 예제를 보며 설명드리겠습니다.
public class Person { public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } public Person(string name, int age, string gender) { Name = name; Age = age; Gender = gender; } public virtual void Eat() // 부모 클래스인 Person의 메서드를 가상함수로 선언 = 'virtual' { Console.WriteLine($"{Name}이(가) 밥을 먹고 있습니다."); } public virtual void Sleep() { Console.WriteLine($"{Name}이(가) 잠을 자고 있습니다."); } public virtual void Dress() { Console.WriteLine($"{Name}이(가) 옷을 입고 있습니다."); } }
C#
복사
public class Coder : Person { public Coder(string name, int age, string gender) : base(name, age, gender) { } public override void Eat() // 자식 클래스인 Coder에서 메서드 오버라이딩 = 'override' { Console.WriteLine($"{Name}이(가) 코딩하면서 밥을 먹고 있습니다."); } public override void Sleep() { Console.WriteLine($"{Name}이(가) 코딩을 하다가 잠이 들었습니다."); } public override void Dress() { Console.WriteLine($"{Name}이(가) 편한 옷을 입고 코딩을 하고 있습니다."); } public void Code() { Console.WriteLine($"{Name}이(가) 코딩을 하고 있습니다."); } }
C#
복사
위의 코드는 Coder라는 자식 클래스에서 Person이라는 부모 클래스의 속성과 기능을 상속받고 부모 클래스의 메서드인 Eat(), Sleep(), Dress()를 재정의하여 Coder.Eat(), Coder.Sleep(), Coder.Dress()의 출력 값을 변형시켰습니다.
이렇게 하여 Person.Eat()을 출력하면 Name이 밥을 먹고 있습니다. 가 출력되지만 Coder.Eat()을 출력하면 Name이 코딩하면서 밥을 먹고 있습니다. 가 출력되게 됩니다.
위에서 보았듯, 자식 클래스는 부모 클래스의 속성이나 기능을 상속받지만, 상속받은 기능을 자식 클래스에서 변경합니다.
즉, 오버라이딩은 상속을 전제로 하며, 상속을 통해 물려받은 메서드를 자식 클래스에서 변경하는 행위입니다.

오버로딩이란?

여러분은 위에서 오버라이딩이 무엇인지 학습했습니다.
그런데 메서드를 재정의하다보면, 매개변수의 개수를 다르게 설정하고 싶을 수 있습니다. 예를 들어, 여러분이 밥을 먹는다는 메서드를 만들었는데 이를 통해 무엇을 먹고 있는지, 얼마나 먹고 있는지 등의 메서드로 변경하고 싶을 수 있습니다. 그럴 때, 사용하는 것이 바로 오버로딩입니다.
오버로딩은 메서드의 이름은 같지만 매개변수 목록이 다른 여러 메서드를 정의하는 것을 의미합니다
이 또한 코딩 예제를 통해 알아보겠습니다.
public class Person { public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } public Person(string name, int age, string gender) { Name = name; Age = age; Gender = gender; } // 기본적인 Eat 메서드 public void Eat() { Console.WriteLine($"{Name}이(가) 밥을 먹고 있습니다."); } // 오버로딩된 Eat 메서드 - 음식의 이름을 매개변수로 받음 public void Eat(string food) { Console.WriteLine($"{Name}이(가) {food}을(를) 먹고 있습니다."); } // 오버로딩된 Eat 메서드 - 음식의 이름과 양을 매개변수로 받음 public void Eat(string food, int amount) { Console.WriteLine($"{Name}이(가) {food}을(를) {amount}g 먹고 있습니다."); } } public class Program { public static void Main(string[] args) { Person person = new Person("John", 30, "Male"); person.Eat(); // 출력: John이(가) 밥을 먹고 있습니다. person.Eat("사과"); // 출력: John이(가) 사과을(를) 먹고 있습니다. person.Eat("사과", 100); // 출력: John이(가) 사과을(를) 100g 먹고 있습니다. } }
C#
복사
이처럼 오버로딩은 메서드가 동일한 기능을 수행하지만, 입력되는 매개변수의 유형이나 수에 따라 다른 방식으로 처리해야 하는 경우에 유용하게 사용할 수 있습니다.

결론

여러분은 이번 학습을 통해 클래스의 정의, 사용 이유 그리고 더 나아가 그와 연관된 개념들까지 알게 되었습니다.
클래스 : 관련된 속성과 메서드를 묶어서 객체를 생성하기 위한 템플릿
속성 : 객체 안에 속한 변수 또는 값
메서드 : 특정 클래스나 객체의 행동을 정의하는 함수적인 개념
객체 : 프로그래밍에서 속성과 기능을 가진 독립적인 데이터 단위
객체를 사용하는 이유 : 데이터와 그 데이터 관련 연산을 묶어 관리하기 위해서
클래스를 사용하는 이유 : 코드를 직관적으로 볼 수 있게 하고, 재사용성과 유지보수에 용이하게 하기 위해서
상속 : 특정 기능(데이터 및 동작)을 제공하는 기본 클래스(부모 클래스)를 정의하고 해당 기능을 상속하거나 재정의하는 파생 클래스(자식 클래스)를 정의할 수 있는 객체 지향 프로그래밍 언어의 기능
오버라이딩 : 부모-자식 상속 관계에 있는 클래스에서 상위 클래스의 메서드를 하위 클래스에서 재정의하는 것
오버로딩 : 메서드의 이름은 같지만 매개변수 목록이 다른 여러 메서드를 정의하는 것
클래스는 객체지향 프로그래밍에서 중요한 개념이므로, 이번 내용을 잘 이해하고 직접 실습해보며 여러분의 코딩 실력 향상에 도움이 됐으면 좋겠습니다.