본문 바로가기

내일배움캠프/꾸준CS과제

[TIL 24.07.05] 05. 상속과 인터페이스

.

 

 

확인 문제

using System;

// 상위 클래스 A
public class A
{
    public virtual void Display()
    {
        Console.WriteLine("Class A Display");
    }
}

// 클래스 B는 클래스 A를 상속받음
public class B : A
{
    public override void Display()
    {
        Console.WriteLine("Class B Display");
    }
}

// 클래스 C는 클래스 A를 상속받음
public class C : A
{
    public override void Display()
    {
        Console.WriteLine("Class C Display");
    }
}

 

1. 위와 같은 코드에서, 다음과 같이 다중 상속을 하는 것이 가능할까요? 가능/불가능하다면 이유는 무엇일까요?

public class D : B, C
{
    
}

불가능하다. C#에서는 클래스의 다중상속을 지원하지 않는다. 

2. 만약 C#에서 다중 상속이 지원되었다면, 클래스 D는 어떤 문제에 직면하게 될까요?

B 클래스와 C 클래스는 A 클래스를 공통의 부모로 두고 있고, 각각 Display 메서드를 오버라이딩하고 있다.

이 상황에서 D 클래스가 B와 C를 동시에 상속받는다면, Display 메서드를 오버라이드할 때 어느 클래스의 것을 기준으로 해야 할지 모호해진다.

이 모호성은 코드의 예측가능성을 떨어트리고, 유지보수가 어렵게 하며 잠재적 버그를 초래할 수 있다.


 

설명 문제

1. 클래스를 다른 클래스로 상속하기 위한 방법은 무엇인가요?

자식클래스의 이름 옆에 콜론을 달고 그 다음 상속할 클래스의 이름을 적는다.

ex) public class ChildClass : ParentClass

2. 클래스 상속에서 다이아몬드 문제(diamond problem)가 발생하는 이유와 이를 해결하는 방법에 대해 설명해주세요.

다이아몬드 문제는 같은 부모를 둔 자식클래스들을 다시 하나의 클래스가 동시에 상속받는 데에서 발생한다. 

클래스의 다중상속을 금지하면 이 문제는 발생하지 않는다.

 

3. 인터페이스란 무엇인가요?

인터페이스는 구현을 제공하지 않되 상속받는 클래스에게 특정 메서드의 구현을 강제하는 코드이다. 다만, C# 8.0 이후로 default 메서드 구현이 가능해졌다. 이 메서드는 자식에서 수정할 수 없다. 

4. 인터페이스와 추상클래스의 차이는 무엇인가요?

인터페이스는 기본적으로 메서드의 구현을 제공하지 않고, 필드도 가지지 않는다. 다만, 프로퍼티를 가질 수는 있다. 

인터페이스는 다중 상속이 가능하다.

 

추상 클래스는 구현이 포함될 수 있으며, 추상 메서드가 아닌 다른 메서드 또는 필드 역시 있을 수 있다.

추상 클래스는 다중 상속이 불가능하다.


 

실습 문제


namespace _05.상속과_인터페이스_실습
{
    interface ILogger
    {
        void WriteLog(string message);
        void WriteError(string error)
        {
            WriteLog($"Error: {error}");
        }
    }

    class ConsoleLogger : ILogger
    {
        // TODO : ConsoleLogger가 현재 시간과 메시지를 콘솔에 출력하는 기능을 추가
        // HINT : DateTime.Now.ToLocalTime() 함수를 이용합니다.
        public void WriteLog(string message)
        {
            Console.WriteLine(DateTime.Now.ToLocalTime() + message);
        }
    }

    class FileLogger : ILogger
    {
        private StreamWriter writer;

        public FileLogger(string path)
        {
            writer = File.CreateText(path);
            writer.AutoFlush = true;
        }

        // TODO : FileLogger가 현재 시간과 메시지를 파일에 기록하는 기능을 추가
        // HINT : writer.WriteLine() 함수를 이용합니다.
        public void WriteLog(string message)
        {
            writer.WriteLine(DateTime.Now.ToLocalTime() + message);
        }
    }

    class ClimateMonitor
    {
        private List<ILogger> loggers = new List<ILogger>();

        // TODO : ConsoleLogger또는 FileLogger의 기능을 가질 수 있는 ClimateMonitor를 작성
        public ClimateMonitor(ILogger logger)
        {
            loggers.Add(logger);
        }

        public void AddLogger(ILogger logger)
        {
            loggers.Add(logger);
        }


        public void Start()
        {
            while (true)
            {
                Console.Write("온도를 입력해주세요. : ");
                string temperature = Console.ReadLine();
                if (temperature == "")
                {
                    WriteAllError("공백을 입력받았습니다.");
                    break;
                }

                WriteAllLog("현재 온도 : " + temperature);
            }
        }

        private void WriteAllLog(string message)
        {
            foreach (var logger in loggers)
                logger.WriteLog(message);
        }

        private void WriteAllError(string error)
        {
            foreach (var logger in loggers)
                logger.WriteError(error);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ClimateMonitor monitor = new ClimateMonitor(new ConsoleLogger());
            monitor.Start();

            Console.WriteLine("이제부터 파일에도 기록됩니다.");

            monitor.AddLogger(new FileLogger("MyLog.txt"));
            monitor.Start();
        }
    }
}

.