오늘 배운 내용은 생성자와 static 관련 내용들 (static 변수, static 메소드, static 클래스)
상속은 내일 다형성과 오버라이딩 배우면서 같이 정리하는것으로.. 아래는 심화문제 풀이..


심화 과제 1

Math와 같은 클래스는 객체를 만들지 않고도 기능들을 만들어 사용할 수 있음을 배웠습니다. 편리한 사용을 위해 본인만의 myHelper 라는 클래스를 만들었다고 가정하겠습니다. 정수 배열을 입력받아 해당 배열의 요소들 중에서 가장 작은 값을 반환하는 정적 메소드를 하나 작성하세요. 요구 사항은 아래와 같습니다.

  • 입력으로 주어지는 배열은 비어있지 않다고 가정합니다.
  • 정적(static) 메서드를 사용하여 구현하여야 합니다
  • 배열의 모든 요소를 반복하여 가장 작은 값을 찾아 반환하여야 합니다.

Main.cs

int min = MyHelper.FindMinimum(new int[]{3,2,10,4,5});
Console.WriteLine("최소값? :" + min);

MyHelper.cs

public static int FindMinimum(int [] intarr)
{
    int min = intarr[0];
    for (int i = 1; i < intarr.Length-1; i++)
    {
        if (intarr[i] < min)
        {
            min = intarr[i];
        }
    }
    return min;
}

심화 과제 2

위의 myHelper 클래스에 정적 메소드를 하나 더 만들겠습니다. 주어진 문자열에서 대문자의 개수를 세는 정적 메소드를 구현하세요. 요구 사항은 아래와 같습니다.

  • 입력으로 주어지는 문자열은 비어있지 않다고 가정하겠습니다.
  • 정적 메서드를 사용하여 구현하여야 합니다.
  • 문자열을 반복하여 대문자의 개수를 세고, 그 개수를 반환하여야 합니다.
  • char형의 내장 기능 중, IsUpper를 활용하면 대문자 여부를 확인 가능합니다.

Main.cs

int count = MyHelper.CountUppers("아이A우에B오000bQ");
int count2 = MyHelper.CountUppers("");
Console.WriteLine("대문자 갯수? : " + count);
Console.WriteLine("대문자 갯수? : " + count2);

MyHelper.cs

public static int CountUppers(string someStr)
{
    int count = 0;
    if (someStr == null)
    {
        Console.WriteLine("지금 장난해?!");
        return count;
    }

    char[] someCharArr = someStr.ToCharArray();
    for (int i = 0; i < someCharArr.Length; i++)
    {
        if (char.IsUpper(someCharArr[i]))
        {
            count++;
        }
    }        
    return count;
}

심화 과제 3 - 업적 시스템

새로운 cs 파일을 만들고, Achievement 클래스를 생성.
아래 구현 사항을 보다가 필요해보이는 내용이 발견되면 자유롭게 추가 구현 ㄱㄱ

일반 필드 및 프로퍼티

  • string Name: 업적 이름
  • string Description: 업적 설명
  • int Goal: 목표 수치
  • int Progress: 현재 진행 수치 (기본값 0)
  • bool IsCompleted: 업적 달성 여부 (기본값 false)

static 필드

  • int TotalAchievements: 생성된 업적의 총 개수를 저장하는 static 필드
  • int CompletedAchievements: 달성된 업적의 총 개수를 저장하는 static 필드

생성자

  • 이름, 설명, 목표 수치를 받아 초기화
  • 생성자가 호출될 때마다 TotalAchievements를 증가.

메서드

  • AddProgress
    • 반환 없음. 인자값으로 int value를 받음
    • Progress에 value를 더하고 목표 수치에 도달했는지 확인
    • 목표를 달성하면:
      • IsCompleted를 true로 설정.
      • CompletedAchievements를 1 증가.
      • “업적 [업적 이름] 달성!” 출력.
  • DisplayInfo
    • 업적 이름, 설명, 목표 및 진행 상황, 달성 여부를 출력
    • 본인 취향껏
  • static 메서드: DisplaySummary
    • 반환 없음
    • 현재 생성된 업적의 총 개수와 달성된 업적의 총 개수를 출력
  • 테스트를 위해 메인으로 이동하여 다음을 작성
  • Achievement 객체를 3개 생성
    • 첫 번째 업적: “초급 도전자”, “점수 100점 달성”, 목표 100
    • 두 번째 업적: “중급 도전자”, “점수 500점 달성”, 목표 500
    • 세 번째 업적: “고급 도전자”, “점수 1000점 달성”, 목표 1000
  • 각 업적의 AddProgress 메서드를 호출하여 진행 상황을 업데이트:
    • 첫 번째 업적에 AddProgress 인자값으로 100
    • 두 번째 업적에 AddProgress 인자값으로 600
    • 세 번째 업적에 AddProgress 인자값으로 800
  • 각 업적의 DisplayInfo를 호출하여 현재 상태를 출력.
  • DisplaySummary를 호출하여 총 업적 및 달성된 업적 개수를 출력.

Main.cs

Achievement[] achievements = new Achievement[4]
{
    new Achievement("10살에 곰을 잡은", "10살에 곰을 잡으면 달성", 10),
    new Achievement("초급 도전자", "100점 달성", 100),
    new Achievement("중급 도전자", "500점 달성", 500),
    new Achievement("고급 도전자", "1000점 달성", 1000)
};

achievements[1].AddProgress(100);
achievements[2].AddProgress(600);
achievements[3].AddProgress(800);

foreach (Achievement ach in achievements)
{
    ach.DisplayInfo();
}

Achievement.DisplaySummary();

Achievement.cs

public class Achievement
{
    private string _name;
    private string _description;
    private int _goal;
    private int _progress;
    private bool _isCompleted;

    private static int _totalAchievements;
    private static int _completedAchievements;

    public Achievement(string name, string description, int goal)
    {
        _totalAchievements++;
        _name = name;
        _description = description;
        _goal = goal;
    }

    private void AddCompletedAchievements()
    {
        _completedAchievements++;
    }
    
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public string Description
    {
        get { return _description; }
        set { _description = value; }
    }

    public int Goal
    {
        get { return _goal; }
        set { _goal = value; }
    }

    public int Progress
    {
        get { return _progress; }
        set { _progress = value; }
    }

    public bool IsCompleted
    {
        get { return _isCompleted; }
        set { _isCompleted = value; }
    }

    public void AddProgress(int value)
    {
        Progress =+ value;
        if (Progress >= Goal)
        {
            Console.WriteLine($"업적 {Name} 달성!");
            IsCompleted = true;
            AddCompletedAchievements();
        }
    }

    /* 현재 업적 정보 */
    public void DisplayInfo()
    {
        Console.WriteLine("===\t업적\t===");
        Console.WriteLine($"{Name}");
        Console.WriteLine($"설명 : {Description}");
        Console.WriteLine($"목표 : {Goal}");
        Console.WriteLine($"현재 상황 : {Progress}");
        Console.WriteLine($"달성 여부 : {IsCompleted}");
    }
    
    /* 업적 달성 요약 */
    public static void DisplaySummary()
    {
        Console.WriteLine("===\t요약\t===");
        Console.WriteLine($"현재 생성된 업적 : {_totalAchievements}");
        Console.WriteLine($"현재 달성된 업적 : {_completedAchievements}");
    }
}

오늘 나왔던 내용중 재미있던 내용들 정리..

자바의 한정자(final)와 c#의 Sealed 한정자

  • Stackoverflow질문글
  • Sealed 마소 레퍼런스
  • Class
    • 자바는 final c#은 sealed로 선언, 동작하는건 동일. 선언하면 클래스의 상속을 막을 수 있다.
  • Method
    • 자식 클래스에서 재정의 불가능한 메서드 선언.
    • 메서드를 virtual이란 키워드로 선언 하지 않는 한 봉인된 메서드에서 방지 가능함? (아마 내일 추가로 배울듯)
  • Variables : 요기가 가장 다름
    • c#은 변수에 sealed가 없다. 다만 const나 readonly를 통해 변수가 변하지 않는다 / 한번만 대입된다를 보장가능
    • 자바에는 매개변수와 필드변수에서 선언하여 바뀌지 않는다 / 한번만 대입된다를 보장 가능.

추가로..

자바 17에서 sealed 키워드가 추가되었는데 Java17 Sealed
이것은 상속을 지정한 클래스에서만 받을수 있도록 하여, c#의 sealed와는 조금 다른것 같다.


한가지 더..

Java 코드

//hello.java
public static void main(String[] args) {
    System.out.println("Hello, World!");
    System.out.println(SomeStaticThings.staticVariable);

    // 자바는? 경고는 뜨는데 되긴됨 ㅋㅋ
    SomeStaticThings someStaticVariable = new SomeStaticThings();
    System.out.println(someStaticVariable.staticVariable);

    someStaticVariable.staticVariable = 3;
    someStaticVariable.printStaticVariable();
}

//SomeStaticThings.java
public class SomeStaticThings {
    public int a = 0;
    public static int staticVariable = 0;

    public static void printStaticVariable() {
        System.out.println(staticVariable);
    }

    public int plusInta(){
        return a++;
    }
}

java


c# 코드

// program.cs
public static void main(string[] args) 
{
    Console.WriteLine("Hello, World!");
    Console.WriteLine(SomeStaticThings.staticVariable);

    SomeStaticThings someStaticVariable = new SomeStaticThings();
    // c#은 접근이 안됨 (컴파일러에서 오류 발생)
    Console.WriteLine(someStaticVariable.staticVariable);

    someStaticVariable.staticVariable = 3;
    someStaticVariable.printStaticVariable();
}

// SomeStaticThings.cs
public class SomeStaticThings
{
    public int a = 0;
    public static int staticVariable = 0;

    public static void printStaticVariable()
    {
        Console.WriteLine(staticVariable);
    }

    public int plusInta()
    {
        return a++;
    }
}

cs
같은 키워드를 다르게 쓰거나 다른 키워드를 언어마다 살짝씩 다르게 씀.. 재미있지 않나요!?