-
객체 지향 프로그래밍 (OOP)C# 2023. 8. 14. 17:00
객체 지향 프로그래밍 (Object-Oriented Programming)
: 컴퓨터 프로그램을 여러 명령어의 목록으로 보지 않고 여러 개의 독립된 객체들의 집합으로 파악하는 프로그래밍 기법.
I. 객체, 클래스, 인스턴스
A. 객체 (object)
: 객체 지향 프로그래밍(OOP) 에서 클래스(class)가 실제로 구현된 인스턴스(instance)
혹은 클래스(class)에서 구현하기 위한 추상적인 개념
: 프로그램에서 사용되는 데이터 혹은 식별자에 의해 참조되는 공간
ex) 고양이라는 개념
B. 클래스 (class)
: 객체 지향 프로그래밍(OOP)에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 템플릿
: 클래스에서는 해당 객체의 속성(state)는 변수(variable)로, 기능(behavior)은 메서드(method)로 정의함.
ex) 고양이라는 객체를 프로그램상 나타내기 위해 변수와 메서드를 정의
internal class Cat { // 속성 정의 public string catName; // 이름은 뭔지 public string catSpecies; // 묘종은 뭔지.. public string color; // 색은 뭔지.. public int catAge; // 나이는 몇 살인지.. // 기능 정의 public void meow() // 야옹하고 울기 { Console.WriteLine("Meow!"); } public void moving() { Console.WriteLine(catName + " is moving..."); // 이동하기 } public void jump() { Console.WriteLine("...Jump!"); // 점프하기 } }
C. 인스턴스 (instance)
: 객체 지향 프로그래밍(OOP)에서 클래스에 소속된 개별적인 객체.
: 정의된 클래스에 객체를 생성한 경우, 그 객체는 해당 클래스의 인스턴스가 된다.
: 하나의 클래스를 사용하여 유사한 성질을 가진 수많은 인스턴스를 생성할 수 있다.
ex) 고양이 "냬옹스(Nyeaons)"는 Cat 클래스의 인스턴스
Nyeaons internal class Program { static void Main(string[] args) { Cat Nyeaons = new Cat(); Nyeaons.catName = "Nyeaons"; // 고양이의 이름은 냬옹스다. Nyeaons.catSpecies = "스코티시폴드"; // 묘종은 스코티시 폴드. Nyeaons.color = "티끌없는 화이트"; // 색깔은 티끌없는 화이트. Nyeaons.catAge = 5; // 나이는 5살. Console.WriteLine($"이 고양이의 이름은 {Nyeaons.catName}다. 묘종은 {Nyeaons.catSpecies}이며, {Nyeaons.color}색을 지닌 귀여운 고양이지"); Console.WriteLine($"나이는 {Nyeaons.catAge.ToString()}살 이다"); Console.WriteLine($"{Nyeaons.catName} 물어!"); Nyeaons.moving(); Nyeaons.jump(); Nyeaons.meow(); } }
>
** 객체의 정의를 보면, "클래스(class)가 실제로 구현된 인스턴스(instance)". 즉, Nyeaons는 인스턴스이자 객체이다.
개념의 혼동을 피하기 위해 chatGPT에 물어보았다..
II. OOP의 4가지 속성
A. 추상화 (Abstraction)
: 프로그램으로 표현하기 위하여, 실제의 개념을 단순화하고 필요한 부분을 강조하여 표현하는 개념.
!! 위에서 고양이에 대한 개념을
속성(Property) : 고양이 이름, 묘종, 색깔, 나이의 데이터로 고양이의 정보를 표현
메서드(Methods) : 우는 행동, 이동하는 것, 점프하는 것으로 고양이의 행동을 나타내는 기능을 표현함.
internal class Cat { // 속성 정의 public string catName; // 이름은 뭔지 public string catSpecies; // 묘종은 뭔지.. public string color; // 색은 뭔지.. public int catAge; // 나이는 몇 살인지.. // 기능 정의 public void meow() // 야옹하고 울기 { Console.WriteLine("Meow!"); } public void moving() { Console.WriteLine(catName + " is moving..."); // 이동하기 } public void jump() { Console.WriteLine("...Jump!"); // 점프하기 } }
B. 캡슐화 (Encapuslation)
: 데이터와 해당 데이터를 다루는 메서드를 하나의 단위로 묶어, 외부의 접근을 제어하고, 데이터를 보호하는 개념.
!! 접근 제한자 (Access Modifier)
: 객체 지향 프로그래밍에서 클래스의 멤버(필드, 메서드, 속성 등)에 대한 접근 권한을 지정하는 키워드
1. public : 모든 외부의 접근을 허가함.
2. private : 같은 클래스 내에서만 접근을 허가함.
3. protected : 같은 클래스 내부와 파생 클래스에서 접근을 허가함.
4. internal : 같은 **어셈블리 내에서 접근을 허가함.
**어셈블리 (assembly)
: NET 런타임 환경에서 실행할 수 있는 코드와 리소스, 메타데이터를 포장하고 배포하는 단위!! 위에서 고양이의 정보(데이터) 와 행동(메서드) 을 하나의 단위로 캡슐화(Cat 클래스) 하였고, 외부 코드(Main) 에서 Cat 클래스를 사용하여 고양이를 다룸.
: 데이터의 보호를 위해서는 데이터의 선언을 필드로 직접 접근하기 보다는 속성(property) 으로 해야한다.
internal class Cat { public string catName; // !! 필드로 직접 접근하는 방식 : 외부 필드에서 변형이 가능하다. private string _catAge // !! 속성으로 접근하는 방식 : 클래스 내에 _catAge 라는 속성을 추가. public string catAge // !! 클래스 외부에서 private 필드에 접근하지 않고 속성을 통해 접근 가능해짐. { get { return _catAge; } set { _catAge = value; } }
: 클래스의 속성을 통해, 외부에서 Cat 클래스의 인스턴스를 생성하거나 속성을 설정할 때, 원하는 방식으로 데이터 처리가 가능해진다.
internal class Cat { public string catName; // !! 필드로 직접 접근하는 방식 : 외부 필드에서 변형이 가능하다. private string _catAge // !! 속성으로 접근하는 방식 : 클래스 내에 _catAge 라는 속성을 추가. public string catAge // !! 클래스 외부에서 private 필드에 접근하지 않고 속성을 통해 접근 가능해짐. { get { return _catAge; } //set { _catAge = value; } set { if (value > 0) { _catAge = value; } else { console.WriteLine("유효하지 않는 나이입니다."); // !! set 접근자의 조건문에 의해 나이가 잘못된 경우를 처리할 수 있게 됨. _catAge = 99; } } } }
C. 상속 (Inheritance)
: 기존 클래스의 속성과 메서드를 새로운 클래스에서 재사용하거나 확장할 수 있게 해주는 개념.
!! 고양이와 비슷한 맥락으로 강아지의 클래스를 만듦.
internal class Dog { // 속성 정의 private string name; public string Name // 이름은 뭔지.. { get { return name; } set { name = value; } } private string dogBreed; public string DogBreed // 견종은 뭔지.. { get; // !! 생략 가능함. set; } private string color; public string Color // 색은 뭔지.. { get; set; } private int age; public int Age // 나이는 뭔지.. { get { return age; } set { if (value > 0) { age = value; } else { Console.WriteLine("유효하지 않은 나이입니다."); age = 99; } } } // 기능 정의 public void bark() // 왈!하고 울기 { Console.WriteLine("Bark!"); } public void moving() { Console.WriteLine(Name + " is moving..."); // 이동하기 } public void jump() { Console.WriteLine("...Jump!"); // 점프하기 } }
>
!! 고양이 클래스와 비교해보았을 때, 다음의 클래스 멤버는 공통적으로 사용이 가능함을 알 수 있다.
속성 : 이름, 나이, 색
메서드 : 이동, 점프!! 고양이와 강아지의 개념의 공통점은 동물이라는 점이다.
==> 해당하는 공유가능한 속성과 메서드를 상위 클래스(Animal) 로 추상화 시킨다면, 상위 클래스로부터 확장된 여러 개의 하위 클래스(Dog, Cat)에서 해당 속성과 메서드들을 간편하게 사용할 수 있다.
class Animal { // properties private string name; public string Name { get; set; } private string color; public string Color { get; set; } private string age; public string Age { get; set; } // methods public void moving() { Console.WriteLine($"{Name}이 움직이기 시작합니다."}; } public void jump() { Console.WriteLine("...JUMP!"}; } }
!! 하위 클래스의 선언은 하위 클래스 : 상위 클래스 로 하여, 상속이 이루어지게 한다.
internal class Dog : Animal { // properties private string dogBreed; public string DogBreed // 견종은 뭔지.. { get; // !! 생략 가능함. set; } // methods public void bark() // 왈!하고 울기 { Console.WriteLine("Bark!"); Console.WriteLine($"{Name}은 발랄하게 가서 물었다"); } } internal class Cat : Animal { // properties private string _catSpecies; public string catSpecies // 묘종은 뭔지.. { get; set; } // methods public void meow() // 야옹하고 울기 { Console.WriteLine("Meow!"); Console.WriteLine("아무 일도 일어나지 않았다."); } }
!! Main에서 실행
Nyeaons & Mungs internal class Program { static void Main(string[] args) { Cat Nyeaons = new Cat(); Nyeaons.Name = "Nyeaons"; // 고양이의 이름은 냬옹스다. Nyeaons.catSpecies = "스코티시폴드"; // 묘종은 스코티시 폴드. Nyeaons.Color = "티끌없는 화이트"; // 색깔은 티끌없는 화이트. Nyeaons.Age = 5; // 나이는 5살. Console.WriteLine($"이 고양이의 이름은 {Nyeaons.Name}다. 묘종은 {Nyeaons.catSpecies}이며, {Nyeaons.Color}색을 지닌 귀여운 고양이지"); Console.WriteLine($"나이는 {Nyeaons.Age.ToString()}살 이다\n\n"); Console.WriteLine($"{Nyeaons.Name} 물어!"); Nyeaons.moving(); Nyeaons.jump(); Nyeaons.meow(); Console.WriteLine("\n\n"); Dog Mungs = new Dog(); Mungs.Name = "Mungs"; // 강아지의 이름은 멍스다. Mungs.DogBreed = "웰시코기"; // 견종은 웰시코기 Mungs.Color = "갓 구운 빵과 같은 풍부한 브라운"; // 색깔은 이하 동문 Mungs.Age = 3; // 나이는 3살 Console.WriteLine($"이 강아지의 이름은 {Mungs.Name}다. 견종은 {Mungs.DogBreed}이며, {Mungs.Color}색을 지닌 귀여운 강아지라구"); Console.WriteLine($"나이는 {Mungs.Age.ToString()}살 이다\n\n"); Console.WriteLine($"{Mungs.Name} 물어!"); Mungs.moving(); Mungs.jump(); Mungs.bark(); Console.WriteLine("\n\n"); } }
>
D. 다형성 (Polymorphism)
: 어떤 객체의 속성이나 기능이 그 맥락에 따라 다른 역할을 수행할수 있는 객체 지향의 특성
메서드 오버라이딩 (Method Overriding)
: 상속 관계에서 자식 클래스가 부모 클래스의 메서드를 재정의하여 사용하는 것.
: 같은 이름의 기능이 다른 역할을 수행할 때 사용.
ex) 위의 코드에서 고양이와 강아지에게 물어! 라고 시켰는데 다른 결과가 나옴. 이를 동일한 이름으로 재정의 한 후, 메서드 오버라이딩을 수행 했을 때.
class Animal { // properties private string name; public string Name { get; set; } // methods public virtual void Command() // 해당 메서드는 오버라이드 가능하다 선언. { Console.WriteLine("동물에게 명령해보았다."); Console.WriteLine($"{Name}이 움직이기 시작합니다."); Console.WriteLine("...JUMP!"); } } class Dog : Animal { public override void Command() // 왈!하고 울기 { Console.WriteLine($"{Name} 물어!"); Console.WriteLine($"{Name}이 움직이기 시작합니다."); Console.WriteLine("...JUMP!"); Console.WriteLine("Bark!"); Console.WriteLine($"{Name}은 발랄하게 가서 물었다"); } } class Cat : Animal { public override void Command() // 야옹하고 울기 { Console.WriteLine($"{Name} 물어!"); Console.WriteLine($"{Name}이 움직이기 시작합니다."); Console.WriteLine("...JUMP!"); Console.WriteLine("Meow!"); Console.WriteLine("아무 일도 일어나지 않았다."); } }
==> Main에서 사용하는 명령 부분을 상당히 줄일 수 있었다.
static void Main(string[] args) { Cat Nyeaons = new Cat(); Nyeaons.Name = "Nyeaons"; // 고양이의 이름은 냬옹스다. Nyeaons.catSpecies = "스코티시폴드"; // 묘종은 스코티시 폴드. Nyeaons.Color = "티끌없는 화이트"; // 색깔은 티끌없는 화이트. Nyeaons.Age = 5; // 나이는 5살. Console.WriteLine($"이 고양이의 이름은 {Nyeaons.Name}다. 묘종은 {Nyeaons.catSpecies}이며, {Nyeaons.Color}색을 지닌 귀여운 고양이지"); Console.WriteLine($"나이는 {Nyeaons.Age.ToString()}살 이다\n\n"); Nyeaons.Command(); /* 이하의 부분이 생략됨. Console.WriteLine($"{Name} 물어!"); Console.WriteLine($"{Name}이 움직이기 시작합니다."); Console.WriteLine("...JUMP!"); Console.WriteLine("Meow!"); Console.WriteLine("아무 일도 일어나지 않았다."); Console.WriteLine("\n\n"); */ // 생략...
ex) 각 동물의 소개를 Iintroduce라는 인터페이스를 활용하여 Main에 적용
인터페이스 (Interface)
: 메서드의 이름, 매개변수, 반환 유형만을 선언없이 정의함으로써, 상속받는 클래스에 해당 메서드를 강제함.
: 다중 상속이 가능함.
: 클래스 간의 관계를 유연하게 설계할 수 있음.
// 소개문 인터페이스 internal interface Iintroduce { string Introduce(); } internal class Dog : Animal, Iintroduce { //.. 생략 public string Introduce() { return ($"이 강아지의 이름은 {Name}다. 견종은 {DogBreed}이며, {Color}색을 지닌 귀여운 강아지라구\n나이는 {Age.ToString()}살 이다\n\n"); } } internal class Cat : Animal, Iintroduce { //.. 생략 public string Introduce() { return ($"이 고양이의 이름은 {Name}다. 묘종은 {catSpecies}이며, {Color}색을 지닌 귀여운 고양이지\n나이는 {Age.ToString()}살 이다\n\n"); } }
==> 마찬가지로, main에서 일일히 적용시켜주지 않아도 됨.internal class Program { static void Main(string[] args) { Cat Nyeaons = new Cat(); Nyeaons.Name = "Nyeaons"; Nyeaons.catSpecies = "스코티시폴드"; Nyeaons.Color = "티끌없는 화이트"; Nyeaons.Age = 5; Console.WriteLine(Nyeaons.Introduce()); // 인터페이스로 인한 소개문 생략 Nyeaons.Command(); // 오버라이드로 인한 명령 부분 생략 Dog Mungs = new Dog(); Mungs.Name = "Mungs"; Mungs.DogBreed = "웰시코기"; Mungs.Color = "갓 구운 빵과 같은 풍부한 브라운"; Mungs.Age = 3; Console.WriteLine(Mungs.Introduce()); Mungs.Command(); } }
>
'C#' 카테고리의 다른 글
조건문과 반복문 (0) 2023.08.15 변수와 자료형 (0) 2023.08.15 C# 개요 (0) 2023.08.14 20230801-temp (0) 2023.08.01 20230726-임시 (0) 2023.07.26