목차
1.Stream / StreamWriter
2. 디렉터리 존재 여부
3. 디렉토리 생성 / 삭제
4. 파일 존재 여부
5. 파일 생성 / 삭제 
6. 파일 읽기 

 

📝 System.IO 네임스페이스

using System.IO;

: 파일 시스템 작업 ( 디렉터리 / 파일 생성, 삭제, 수정 )에 관한 기능 제공 

: 텍스트 파일 작업 ( 파일 데이터 읽기 쓰기 )에 관한 기능 제공 

 

→ 더 많은 Syatem.IO 네임스페이스 기능

https://learn.microsoft.com/ko-kr/dotnet/standard/io/common-i-o-tasks

 

공통적인 I/O 작업 - .NET

.NET의 System.IO 네임스페이스에 있는 클래스와 메서드를 사용하여 공통적인 파일 작업 및 공통적인 디렉터리 작업을 수행하는 방법을 알아봅니다.

learn.microsoft.com

 

📝 1. Stream / StreamWriter

□ Stream 클래스

    ■ 마이크로소프트의 홈페이지의 설명에는 " 바이트 시퀀스의 제네릭 뷰를 제공"라는 표현을 사용한다.

    ■ 바이트 시퀀스란?

          □ 연속된 바이트들의 나열 

           텍스트파일/이미지파일/음악파일 이 저장될 때 바이트들의 시퀀스들로 저장된다. 

    ■ 제네릭 뷰?

           데이터가 무엇이든(텍스트, 이미지, 음악 등) 모두 바이트로 보고 처리할 수 있게 해주는 제네릭을 사용한다.

 

예시 )

타입이 다른 파일을 다룰때, 동일한 steam을 사용한다. 

// 텍스트 파일을 다룰 때도 Stream 사용 가능
FileStream textFile = File.OpenRead("text.txt");

// 이미지 파일을 다룰 때도 동일한 Stream 사용 가능
FileStream imageFile = File.OpenRead("image.jpg");

 

□ TextWriter

    ■ 일련의 문자를 순차적으로 작성할 수 있는 작성기 ( 추상 클래스)

  StreamWriter

    ■ TextWriter을 상속받아 실제로 구현한 클래스 

    ■ 문자를 바이트로 변환해서 Stream에 쓰는 실제 작업을 수행 

 

📝 2. 디렉토리 존재 여부 

Directory.Exists(savepath)

□ Bool 값을 반환

    ■ 해당 경로에 디렉터리가 존재하면 → true

    ■ 해당 경로에 디렉토리가 존재하지 않으면 → false 

 

📝 사용

using System.IO;

internal class Program
{
    static void Main(string[] args)
    {
        string savePath = @"D:\SpartaCodingClub\TextRPGSaveFile\";
        string saveFileName = "SaveFile";

        // 해당 디렉토리 (폴더) 가 없으면 생성
        if (!Directory.Exists(savePath))
        {
            Console.WriteLine("세이브 파일이 있습니다. ");
        }
        else 
        {
            Console.WriteLine("세이브 파일이 없습니다. ");
        }    
        }
    }
}

 

📝 3. 디렉토리 생성 / 삭제

📝 생성

Directory.CreateDirectory(savePath);

□ DirectoryInfo값을 반환

    ■ 지정된 경로에서 디렉터리를 나타내는 개체

📝 삭제

diretoryInfo.Delete();

□ DirectoryInfo에 저장된 디렉터리를 삭제 

 

📝 사용

using System.IO;

internal class Program
{
    static void Main(string[] args)
    {
        string savePath = @"D:\SpartaCodingClub\TextRPGSaveFile\";
        string saveFileName = "SaveFile";

        // 디렉토리 생성 
        DirectoryInfo di = Directory.CreateDirectory(savePath);

        // 디렉토리 삭제
        di.Delete();
    }
}

 

📝 4. 파일 존재 여부

File.Exists(savePath + saveFileName)

□ Bool 값을 반환 

    ■ 해당 경로에 파일이 존재하면 → true

    ■ 해당 경로에 파일이 존재하지 않으면 → false 

 

📝 사용

    internal class Program
    {
        static void Main(string[] args)
        {
            string savePath = @"D:\SpartaCodingClub\TextRPGSaveFile\";
            string saveFileName = "SaveFile";

            if (File.Exists(path))
            {
                 Console.WriteLine("파일이 존재합니다.");
            }
        }
    }

 

📝 5. 파일 생성 / 삭제

📝 생성

File.CreateText(파일명이 포함된 경로)

 StreamWriter 을 반환

이미 해당경로에 파일이 있는 경우 해당 내용이 바뀐다. 

 

📝 삭제

File.Delete(savePath + saveFileName);

해당 경로에 있는 파일을 삭제

 

📝 사용 

    internal class Program
    {
        static void Main(string[] args)
        {
            string savePath = @"D:\SpartaCodingClub\TextRPGSaveFile\";
            string saveFileName = "SaveFile";

            // 저장경로에 생성
            using (StreamWriter sw = File.CreateText(savePath + saveFileName))
            {
                sw.WriteLine("Hello ");
                sw.WriteLine("I'm ");
                sw.WriteLine("a talking potato.");
            }

        }
    }

 

📝 5. 파일 읽기 

File.ReadAllText(파일명이 포함된 경로);

□ string을 반환

    ■  파일의 모든 텍스트를 포함하는 문자열

 

📝 사용 

internal class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello, World!");
        //GameManger.Instance.EnterGame();

        string savePath = @"D:\Window11_TextRPG\";
        string saveFileName = "TestFile";

        string desString = File.ReadAllText(savePath + saveFileName);
    }
}

 


📝 Json 타입의 문자열을 저장하고 불러오는 과정 

https://youcheachae.tistory.com/32

 

[c#][TextRPG] 2. NewtonJson으로 직렬화&역직렬화

목차1. 저장 시스템    □ 설계 2. 저장    □ NuGet     □ Newtonsoft.Json    □ Json    □ 직렬화 / 역직렬화    □ visual Studio에서 사용방법    □ 실제 사용 예시 📝 저장 시스템: nuget의 NewtonJ

youcheachae.tistory.com


 

📝 참고한 링크 

https://learn.microsoft.com/ko-kr/dotnet/api/system.io.directory.createdirectory?view=net-8.0

 

Directory.CreateDirectory 메서드 (System.IO)

지정된 경로에 모든 디렉터리를 만듭니다.

learn.microsoft.com

https://learn.microsoft.com/ko-kr/dotnet/api/system.io.file.createtext?view=net-9.0

 

File.CreateText(String) 메서드 (System.IO)

UTF-8로 인코딩된 텍스트를 쓰기 위해 파일을 만들거나 엽니다. 파일이 이미 있는 경우 해당 내용이 바뀝니다.

learn.microsoft.com

https://learn.microsoft.com/ko-kr/dotnet/api/system.io.stream?view=net-8.0

 

Stream 클래스 (System.IO)

바이트 시퀀스의 제네릭 뷰를 제공합니다. 추상 클래스입니다.

learn.microsoft.com

https://learn.microsoft.com/ko-kr/dotnet/api/system.io.streamreader.-ctor?view=net-8.0

 

StreamReader 생성자 (System.IO)

지정된 스트림에 대한 StreamReader 클래스의 새 인스턴스를 초기화합니다.

learn.microsoft.com

 


📝 깃허브

https://github.com/kimYouChae/SpartaCodingClub

 

GitHub - kimYouChae/SpartaCodingClub

Contribute to kimYouChae/SpartaCodingClub development by creating an account on GitHub.

github.com

 

목차
1. 저장 시스템
    □ 설계 
2. 저장
    □ NuGet 
    □ Newtonsoft.Json
    □ Json
    □ 직렬화 / 역직렬화
    □ visual Studio에서 사용방법
3. 실제 사용 예시

 

📝 1. 저장 시스템

: nuget의 NewtonJson을 사용하여 클래스를 직렬화 한 뒤 텍스트파일로 저장

: 저장된 텍스트 파일을 불러와서 역직렬화 

 

1. 설계

 

 

 

📝 2. 저장 

1. Nuget

: c# 저장방식을 검색하다 보면  nuget의 NewtonJson을 사용하는 글이 많이 보인다. nuget이 뭘까?

 

https://www.nuget.org/

 

NuGet Gallery | Home

The NuGet Gallery is the central package repository for NuGet, the package manager for .NET.

www.nuget.org

:  " NuGet is the package manager for. NET." 즉 닷넷의 패키지 매니저이다.

 

https://learn.microsoft.com/ko-kr/nuget/quickstart/install-and-use-a-package-in-visual-studio

 

빠른 시작: Visual Studio에서 NuGet 패키지 설치 및 사용(Windows에만 해당)

이 빠른 시작에서는 Windows용 Visual Studio 프로젝트에서 NuGet 패키지를 설치하고 사용하는 방법을 알아봅니다.

learn.microsoft.com

: NuGet 패키지에는 다른 개발자가 프로젝트에서 사용할 수 있도록 만든 재사용 가능한 코드가 포함되어 있다. 

 

2. Newtonsoft.Json

: JSON 관련 작업을 할 때 편리한 기능을 제공하는 JSON 라이브러리 

 

3.Json

📝 what is Json 

     Java Script Object Notation의약자 

    데이터를 저장하고 전송하기 위한 형식

📝Json Data

      이름/값 쌍( 키/값 쌍 )으로 구성된다 

       JSON에서는 키는 큰따옴표로 묶인 문자열이어야 한다

{
  "name": "John",
  "age": 30
}

 

→ 더 자세한 내용은 w3 school 홈페이지 참고!

https://www.w3schools.com/js/js_json_syntax.asp

 

W3Schools.com

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

4. 직렬화 / 역직렬화 

📝Serialization (직렬화)

  문자열/숫자/객체/배열/bool/null 등의 타입을 json 문자열로 변환하는 과정

  JsonConvert.SerializeObject 사용

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };

string json = JsonConvert.SerializeObject(product);

 

📝 Deserializaion (역직렬화)

  json 문자열을 문자열/숫자/객체/배열/bool/null 등의 타입으로 재변환하는 과정, 직렬화의 반대과정 

JsonConvert.DeserializeObject <T> 사용

string json = @"{
  'Name': 'Bad Boys',
  'ReleaseDate': '1995-4-7T00:00:00',
  'Genres': [
    'Action',
    'Comedy'
  ]
}";

Movie m = JsonConvert.DeserializeObject<Movie>(json);

 


5. visual Studio에서 사용방법

□ 솔루션 탐색기 우클릭 → Nuget 패키지 관리 선택

□ newton 검색 후 다운로드

 

📝 3. 실제 사용 

1. 직렬화 & 저장

 // 직렬화 된 string 반환
 private string SerializedObject() 
 {
     try 
     {
         PlayerSaveData data = new PlayerSaveData();
        
        // 직렬화
         string json = JsonConvert.SerializeObject(data);

         //Console.WriteLine(json);
         return json;
     }
     catch (Exception e) 
     {
         Console.WriteLine($"직렬화 중 오류 발생 : {e.Message}");
         return string.Empty;
     }
   
 }
public void SaveData() 
{
    Console.WriteLine("데이터를 저장합니다.");

    // 직렬화
    string jsonString = SerializedObject();

    // 해당 디렉토리 (폴더) 가 없으면 생성
    if (!Directory.Exists(savePath))
        Directory.CreateDirectory(savePath);

    // string을 textFile로 저장
    // 파일이 이미 있으면 덮어씀
    using (StreamWriter sw = File.CreateText(savePath + saveFileName))
    {
        sw.WriteLine(jsonString);
    }
}

 

2. 역직렬화 / 불러오기 

 public void LoadData() 
 {
     // 경로 + 파일명에 파일이 있으면 ?
     if (File.Exists(savePath + saveFileName))
     {
         Console.WriteLine(" 저장파일이 있습니다.");

         // 불러오기 
         string desString = File.ReadAllText(savePath + saveFileName);

         // 역 직렬화
         try
         {
             PlayerSaveData data = JsonConvert.DeserializeObject<PlayerSaveData>(desString);
         }

         catch (Exception e) { Console.WriteLine(e); }
     }
     else 
     {
         Console.WriteLine(" 저장파일이 없습니다.");
     }
 }

 


📝디렉토리/텍스트파일을 저장하고 불러오는 방법

https://youcheachae.tistory.com/33

 

[c#][TextRPG] 3. c#의 System.IO를 이용한 파일 시스템 작업

목차1.Stream / StreamWriter2. 디렉터리 존재 여부3. 디렉토리 생성 / 삭제4. 파일 존재 여부5. 파일 생성 / 삭제 6. 파일 읽기  📝 System.IO 네임스페이스using System.IO;: 파일 시스템 작업 ( 디렉터리 / 파

youcheachae.tistory.com


📝 깃허브

https://github.com/kimYouChae/SpartaCodingClub

 

GitHub - kimYouChae/SpartaCodingClub

Contribute to kimYouChae/SpartaCodingClub development by creating an account on GitHub.

github.com

 

목차
1. Scene 관리 시스템
    □ 의도
    □ 설계
2. Scene 관리 구현방법과 상세 설명
    □ IScene 인터페이스
    □ GameManager
    □ 전환 관리
    □ 실제 사용 예시
3. 싱글톤 시스템
    □ 의도
    □ 설계
    □ 개선사항
4. 싱글톤 구현방법과 상세설명

 

📝 Scene 관리 시스템

1. 의도

: 게임의 각 상태 (로비, 인벤토리, 상점 등)를 Scene으로 관리하고, Scene 간의 전환을 관리하기 위해서 

 

2. 설계

□ SceneType라는  Enum을 통해 게임 Scene 타입 정의

□ IScene 인터페이스를 통해 각 Scene을 공통된 타입으로 관리

□ 씬 전환을 GameManager 를 통해 중앙에서 관리

 

📝 Scene 관리 구현방법과 상세 설명 

1. IScene 인터페이스

interface IScene
{
    // 씬에 들어갔을 때 
    public void SceneEntry();

    // 씬에서 메인으로 동작할 로직
    public void SceneMainFlow();
}

: 각 Scene이 필수로 구현해야할 동작을 정의한다.

          □ SceneEntry()

                     ■ Scene에서 초기 화면 구성 등의 기능이 실행된다.

          □ SceneMainFlow()

                       각 Scene에서 필요한 플레이어 입력처리, 상태 업데이트, 화면 출력 등의 기능이 실행된다.

 

2. 📝 GameManager.cs

enum SceneType 
{
    LobbyScene,
    PlayerScene,
    InventoryScene,
    StoreScene,
    RestScene,
    DungeonScene
}

class GameManger : Singleton<GameManger>    
{
    // 씬 저장 리스트 
    private IScene[] gameScene;
    private IScene nextScene;
    private IScene preScene;

    public GameManger() 
    {
        int temp = Enum.GetNames(typeof(SceneType)).Length;
        gameScene = new IScene[temp];

        gameScene[(int)SceneType.LobbyScene]        = LobbyScene.Instance;
        gameScene[(int)SceneType.PlayerScene]       = PlayerManager.Instance;
        gameScene[(int)SceneType.InventoryScene]    = InventoryManger.Instance;
        gameScene[(int)SceneType.StoreScene]        = StoreManager.Instance;
        gameScene[(int)SceneType.RestScene]         = RestScene.Instance;
        gameScene[(int)SceneType.DungeonScene]      = DungeonScene.Instance;

        nextScene = gameScene[0];
    }
}

□  Scene관리를 위한 배열 

           ■ IScene 인터페이스 타입의 배열을 선언 -> 모든 Scene을 하나의 컨테이너에서 관리

            nextScene과 preScene 변수를 통해 Scene 전환 추적 가능 

□   Scene 등록

           ■ SceneType enum의 개수 만큼 배열 크기 동적할당

            enum 값을 인덱스로 활용하여 Scene 인스턴스를 매핑 

 

3. 씬 전환 관리

public void ChangeScene(SceneType type) 
{
    // 지금 씬 = 예전 씬으로
    preScene = nextScene;

    // 현재 씬 지정 
    nextScene = gameScene[(int)type];

    // 현재씬 실행 
    if (preScene != nextScene)
        nextScene.SceneEntry();

    nextScene.SceneMainFlow();
}

□ 전환 로직  

           ■  이전 Scene 기록을 통해 히스토리 관리             

           ■  SceneType enum의 인덱스에 해당하는 Scene을 현재 Scene으로 지정

□ Scene Entry() 실행

           ■  이전 씬과 다른 Scene Type의 Scene인 경우에만 SceneEntry()를 실행

           ■   불필요한 출력 방지 

□ Scene MainFlow() 실행 

           ■  해당 Scnen의 주요 기능 실행 

           ■  입력처리 / 상태 업데이트 / 화면 출력 등을 실행 

 

4. 실행 예시 

 

-📝 LobbyScene.cs

private void ChangeScene(int input) 
{  
    switch (input) 
    {
        case 0:
            // 플레이어 출력 
            PlayerManager.Instance.printPlayer();
            // 로비로 씬 전환 
            GameManger.Instance.ChangeScene(SceneType.LobbyScene);
            break;
        case 1:
            // 인벤토리로 씬 전환 
            GameManger.Instance.ChangeScene(SceneType.InventoryScene);
            break;
        case 2:
            // 상점으로 씬 전환 
            GameManger.Instance.ChangeScene(SceneType.StoreScene);
            break;
        case 3:
            // 던전 씬 전환
            GameManger.Instance.ChangeScene(SceneType.DungeonScene);
            break;
        case 4:
            // 휴식
            GameManger.Instance.ChangeScene(SceneType.RestScene);
            break;
        case 5:
            // 저장 
            GameManger.Instance.SaveData();
            break;
        default:
            Console.WriteLine("잘못된 접근입니다. 다시 로비로 돌아갑니다");

            // Lobby로 돌아가기
            GameManger.Instance.ChangeScene(SceneType.LobbyScene);
            break;

    }
}

□  ChangeScene(int input) 

           ■   사용자 입력(input)에 따라 적절한 Scene으로 이동


📝 Singleton 관리 

1. 의도

: 유니티 프로젝트를 하면서 싱글톤을 상위 클래스로 만들어서 관리한 적이 있는데 편리했던 기억이 있어서 c#에서도 편리할 거라고 예상했다. 

 

2. 설계

□ 제네릭을 사용하여 다양한 타입의 클래스를 생성할 수 있도록 선언

 

3. 개선사항

: 상속을 사용하지 않고 클래스에 static을 붙여 전역에서 사용하는 방법도 가능할 것 같다.

 

📝 Singleton관리 구현방법과 상세 설명 

 

1. 📝 Singleton<T>.cs

class Singleton<T>
    where T : class , new()
{
    private static T instance;

    public static T Instance
    {
        get 
        {
            if (instance == null)
                instance = new T();

            return instance;
        }
    }

}

□ 제네릭 <T>

           ■  다양한 참조 타입의 인스턴스 생성이 가능

           ■  where 제약조건을 통해 <T>는 참조타입 class와 매개변수가 없는 생성자를 가진 클래스만 허용

□ Instance 프로퍼티

           ■  최초 호출 시 인스턴스를 생성하며, 이후에는 동일한 인스턴스를 반환 

 


📝 깃허브

https://github.com/kimYouChae/SpartaCodingClub

 

GitHub - kimYouChae/SpartaCodingClub

Contribute to kimYouChae/SpartaCodingClub development by creating an account on GitHub.

github.com

 


📝 추후

: 저장시스템

: 아이템 구조 or 관리 방법

Interface란 

- 무엇을 해야 하는가에 대한 정의

     - 어떻게 구현할지는 명시하지 않는다.

- 실제로 "어떻게 구현하는가"는 하위 클래스에서 구현.

 

인터페이스의 특징 

1. 접근 제한 한정자를 가질 수 없다. public으로만 선언 가능하다.

: private으로 선언할 수 없다. 

 

2. 필드(변수)를 선언할 수 없다.

 

3. 인터페이스에 선언되는 메서드는 구현부를 가지지 않는다.

internal interface Interface1
{

    public 반환형 메서드이름();
    public 반환형 메서드이름();

    public int myProperty { get; set; }
}

 

c# 8.0 버전은 조금 다르다 그냥 참고만 하자! 

더보기

c# 8.0 버전에는 인터페이스의 메서드가 구현부를 가질 수 있다.

internal interface Interface1
{

    public 반환형 메서드이름 ();

    반환형 메서드이름()
    {
        Console.WriteLine("기본 구현입니다.");
    }

    public int myProperty { get; set; }
}

 

 

4. 클래스는 여러 인터페이스를 상속받을 수 있다.

interface Outerface2 
{
    public void OuterfaceMethod();
}

// 인터페이스 두개를 상속받은 클래스 
public class abcClase : Interface1 , Outerface2
{
        
}

 

5. 상속받은 인터페이스의 메서드를 반드시 구현해야 한다.

: 구현하지 않으면 "인터페이스 멤버를 구현하지 않습니다"라는 오류가 뜬다.

 

6. 인터페이스를 구현한 클래스의 인스턴스는 모두 같은 인터페이스 타입이다.

internal interface Interface1
{

    public void TestFunction();
}

// 인터페이스를 상속받는 클래스 1
public class temp1 : Interface1
{
    public void TestFunction()
    {
        
    }
}

// 인터페이스를 상속받는 클래스 2 
public class temp2 : Interface1
{
    public void TestFunction()
    {

    }
}

 

    static void Main(string[] args)
    {
        Interface1[] inter = new Interface1[2];
        inter[0] = new temp1();
        inter[1] = new temp2();
    }

: temp1과 temp2 클래스는 모두 Interface1이라는 인터페이스를 상속받았으므로 같은 타입이다. 

 

7. 인터페이스 안에는 메서드뿐만 아니라 프로퍼티 / 인덱서 / 이벤트도 가능하다.

출처 : microsoft 공식 c# interface 문서

 

 

8. 인터페이스는 인스턴스를 만들 수 없다.

 

 


추상클래스 vs interface

  추상클래스 abstract class 인터페이스 interface
공통점  
메서드 오버라이딩 하위 클래스는 반드시 메서드를 오버라이딩 해야한다.
인스턴스 인스턴스화 ( ex)new 키워드 사용 ) 불가능 
차이점    
필드 가질 수 있다. 가지지 못한다.
상속 인터페이스와 클래스 모두 상속가능 인터페이스 밖에 상속받지 못함.
생성자 가질 수 있다. 가지지 못한다.
메서드 구현  메서드 구현가능 메서드 구현 불가능

 


인터페이스 명명 규칙 

: 인터페이스 이름은 대문자 "I"로 시작한다.

public interface IAttack
{
    void IAttackMethod();
}

public interface ITracking 
{
    void ITrackinMethod();
}

도움이 된 링크
<interface>

https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/interface

 

interface 키워드 - C# reference

'인터페이스' 키워드를 사용하여 모든 구현 형식이 지원해야 하는 계약을 정의합니다. 인터페이스는 관련되지 않은 형식 집합 간에 공통 동작을 만드는 수단을 제공합니다.

learn.microsoft.com

 

<명명규칙>

https://learn.microsoft.com/ko-kr/dotnet/csharp/fundamentals/coding-style/identifier-names

 

식별자 이름 - 규칙 및 관례 - C#

C# 프로그래밍 언어의 유효한 식별자 이름에 대한 규칙을 알아봅니다. 또한 .NET 런타임 팀과 .NET 문서 팀에서 사용하는 일반적인 명명 규칙을 알아봅니다.

learn.microsoft.com

 

 

🔥 메서드 오버로딩과 오버라이딩의 용어가 헷갈려서 작성하는 포스트 🔥


메서드 오버로딩  (overloading)

같은 이름의 메서드를 중복하여 정의하는 것
: 매개변수의 개수나 타입이 달라야 함
: 객체 지향 프로그래밍의 특징 중 하나인 "다형성"의 특징

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public void SettingMonster() 
    {
            
    }
    public void SettingMonster(int hp)
    {

    }
    public void SettingMonster(int hp , string name)
    {

    }
    public void SettingMonster(int hp, string name , float damage)
    {

    }
}

: 함수이름은 "SettingMonster"로 같다

1. 첫 번째 메서드는 매개변수가 없다.

2. 두 번째 메서드는 int를 매개변수로 가진다.

3. 세 번째 메서드는 int, string을 매개변수로 가진다

4. 네 번째 메서드는 int, string, float를 매개변수로 가진다.

=> 메서드 오버로딩

 

- 생성자 오버로딩

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public Monster() 
    {
    
    }
    public Monster(int hp)
    {

    }
    public Monster(int hp , string name)
    {

    }
    public Monster(int hp, string name , float damage)
    {

    }
}

: 생성자 또한 오버로딩 할 수 있다. 

 

- 생성자 오버로딩 사용 

    public Monster()
    {
        Console.WriteLine("매개변수가 없는 생성자입니다.");
    }
    public Monster(int hp)
    {
        this.hp = hp;
        Console.WriteLine($"하나의 매개변수를 가지는 생성자 입니다 {this.hp}");
    }
    public Monster(int hp, string name)
    {
        this.hp = hp;
        this.name = name;
        Console.WriteLine($"두개의 매개변수를 가지는 생성자 입니다 {this.hp} / {this.name}");
    }
    public Monster(int hp, string name, float damage)
    {
        this.hp = hp;
        this.name = name;
        this.damage = damage;
        Console.WriteLine($"세개의 매개변수를 가지는 생성자 입니다 {this.hp} / {this.name} / {this.damage}");
    }

: 출력 시 해당 메서드가 실행되었는지 확인하기 위해서 출력문을 작성하였다.

 

- 실행

        static void Main(string[] args)
        {
            // 1. 매개변수가 없는 생성자 
            Monster monster = new Monster();

            // 2. 매개변수가 한개인 생성자
            Monster monster2 = new Monster(10);

            // 3. 매개변수가 두개인 생성자
            Monster monster3 = new Monster(10 , "SLIME");

            // 4. 매개변수가 세개인 생성자
            Monster monster4 = new Monster(10 , "SLIME" , 20f);
        }

: 입력된 매개변수와 유형에 따라 적절한 생성자가 매칭된다.

 

- 출력

 

- 그래서 오버로딩을 왜 사용할까?

1. 메서드에 사용되는 이름을 절약할 수 있다. 
2. 같은 기능을 하는 메서드를 하나의 이름으로 정의할 수 있다.

 

- 만약 오버로딩을 사용하지 않고 SettingMonster() 메서드를 사용해 보겠다.

        public class Monster
        {
            protected int hp;
            protected string name;
            protected float damage;

            public void SettingMonster_NoneParemeter()
            {

            }
            public void SettingMonster_OneParemeter(int hp)
            {
               
            }
            public void SettingMonster_TwoParemeter(int hp, string name)
            {

            }
            public void SettingMonster_TreeParemeter(int hp, string name, float damage)
            {
              
            }
        }

: 파라미터가 없는 메서드, 한 개만 있는 메서드, 두 개 있는 메서드, 세 개 있는 메서드 이름을 다 다르게 해야 한다.

: 해당 메서드는 Monster의 필드를 세팅해 주는 같은 역할을 하는데, 이름이 다 다르다. 

-> 사용할 때 불편하다! 


메서드 오버라이딩  (overriding)

: 상속받은 부모 클래스의 메서드를 '자식클래스'에서 재정의 하여 사용하는 것
: 자식클래스에서 오버라이딩할 메서드와 이름, 매개변수의 개수와 타입, 반환값이 같아야 함

 

- 함수이름만 같다면? 

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public void Attack() 
    {
        Console.WriteLine("Monster의 Attack");
    }

}

public class Orc : Monster 
{
    public void Attack() 
    {
        Console.WriteLine("Orc의 Attack");
    }
}

static void Main(string[] args)
{
    Orc orc = new Orc();
    orc.Attack();
}

: 부모 메서드와 이름이 같은 메서드를 작성했을 때

 

-출력

: Orc클래스의 Attack() 메서드에 커서를 가져다 대면

: " 상속된 Attack() 메서드를 숨깁니다 "라는 경고문구가 뜬다. 

: new 키워드를 사용하라고 한다.

        public class Orc : Monster 
        {
            public new void Attack() 
            {
                Console.WriteLine("Orc의 Attack");
            }
        }

: new 키워드를 사용함으로써, 상위 메서드와는 다른 새로운 메서드를 정의한다고 할 수 있다.

 

- virtual , override 키워드 사용하기 

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public virtual void Attack() 
    {
        Console.WriteLine("Monster의 Attack");
    }
}

public class Orc : Monster 
{
    public override void Attack() 
    {
        Console.WriteLine("Orc의 Attack");
    }
}

static void Main(string[] args)
{
    Orc orc = new Orc();
    orc.Attack();

}

: 부모클래스에서 virtual, 자식클래스에서 override 키워드를 사용함으로써 "오버라이딩"을 명시적으로 표현한다.

 

- return 타입이 같아야 한다

: 오버라이딩 하는 메서드의 반환타입이 같아야 한다. 

: 상위 Attack()은 void일 때 오버라이딩 한 메서드의 return 타입을 바꾸게 되면 오류가 난다. 

 

- base 키워드

        public class Orc : Monster 
        {
            public void Attack() 
            {
                base.Attack();
                Console.WriteLine("Orc의 Attack");
            }

        }

: base 키워드를 사용하게 되면 부모의 Attack() 메서드도 실행한다.

 

-출력

 


오버로딩한 메서드를 오버라이딩

: 코드를 작성하다 보면 오버로딩과 오버라이딩을 같이 사용하는 경우가 많은 것 같다.

 

- Monster 클래스

public class Monster
{
    protected int hp;
    protected string name;
    protected float damage;

    public virtual void Attack() 
    {
        
    }
    public virtual void Attack(float stage) 
    { 
    
    }
    public virtual void Attack(float stage, float critical) 
    {
    
    }
}

: 메서드 오버로딩을 사용하여 같은 이름의 메서드를 3개 정의했다. 

 

- Orc 클래스

 public class Orc : Monster 
 {
     public Orc(int h , string n, float d) 
     {
         this.hp = h;
         this.name = n;
         this.damage = d;
     }

     public override void Attack()
     {
         Console.WriteLine($"오크의 기본 공격: {damage * 1.5f} 데미지");
     }

     public override void Attack(float stage)
     {
         Console.WriteLine($"오크의 스테이지 {stage} 기반 공격: {damage * stage * 1.5f} 데미지");
     }

     public override void Attack(float stage, float critical)
     {
         Console.WriteLine($"오크의 크리티컬 공격: {damage * stage * critical * 1.5f} 데미지");
     }
 }

: 메서드 오버라이딩을 통해서 하위 Orc 클래스에서 재정의했다.

: 오버로딩한 Attack() 메서드를 오버라이딩 했다! 

 

- Main

        static void Main(string[] args)
        {
            Orc orc = new Orc(100, "오크", 10f);

            orc.Attack();                   // 기본 공격
            orc.Attack(2.0f);               // 스테이지 기반 공격
            orc.Attack(2.0f, 1.5f);         // 크리티컬 공격
        }

 

- 출력

 


<마치며>

가상함수에 대해 찾아보던 중, 정적바인딩과 동적바인딩에 관해서 알게 되었다. 
추후 공부 후 정적/동적바인딩에 대해서도 블로그글을 작성하고 싶다. 


<도움이 되었던 링크>

https://www.tcpschool.com/java/java_usingMethod_overloading

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

https://www.tcpschool.com/java/java_inheritance_overriding

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 

+ Recent posts