interface

CJB_ny·2022년 7월 25일
0

C#

목록 보기
16/24
post-thumbnail

인터페이스는 메소드, 이벤트, 인덱서, 프로퍼티 만들 가질 수 있다.

그런데 그나마도 "구현부"가 음슴.

또한 인터페이스는 접근 제한 한정자를 사용할 수 없고, 모든 것이 public으로 선언된다.

또한 인터페이스는 객체도 만들 수 없다.

클래스 내부에 구현을 해서
파생클래스가 구현하도록 해주어야한다.

파생클래스는 인터페이스에 선언된 모든 메소드 (및 프로퍼티)를 구현해주어야 하며, 이 메소드들은

public한정자로 수식해아한다.

인터페이스를 상속받는 클래스

Class TestClass : ILogger
{
	public void WriteLog(); // 이 인터페이스 반드시 구현해야함.
}

파생클래스 기반 클래스의 관계와 같이

TestClass의 객체는 ILogger의 객체로 취급할 수 있다.

namespace TestCSharp
{
    interface ILogger
    {
        void WriteLog(string msg);
    }
    class ConsoleLogger : ILogger
    {
        public void WriteLog(string msg)
        {
            Console.WriteLine($"{DateTime.Now.ToLocalTime()} {msg}");
        }
    }
    class FileLogger : ILogger
    {
        private StreamWriter _writer;

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

        public void WriteLog(string msg)
        {
            _writer.WriteLine($"{DateTime.Now.ToLocalTime()} {msg}");
        }
    }

    class Climate
    {
        private ILogger logger;
        public Climate(ILogger logger)
        {
            this.logger = logger;
        }
        public void start()
        {
            while(true)
            {
                Console.WriteLine(" 온도를 입력해 주세요 ");
                string temp = Console.ReadLine();
                if (temp == "")
                    break;

                logger.WriteLog($"현재 온도 : {temp}");
            }
        }
    }
    public class Program
    {
        
        static void Main(string[] args)
        {
            Climate m = new Climate( new FileLogger("MyLog.txt") );

            m.start();
         
        }
    }
}

Main안에서 new Climate 의 인자로 new ConsoleLogger, new FileLogger 를 넘겨줄 수 있다.

(FileLogger의 경우 텍스트 파일 생성함)

죽음의 다이아몬드

R이라는 클래스의 Ride라는 함수가 있고, Car, Plane이라는 클래스도 R을 상속받아

오버라이딩 했다고 하자.

이 두개의 클래스를 MyVehicle이라는 클래스가 상속받았다고 하면은

누구의 Ride 함수를 구현해야 할까?

죽음의 다이아몬드의핵심은 "모호성"이다.

클래스이름함수상속여부
RidableRide부모
CarRide()Ridable을 상속받음
PlaneRide()Ridable을 상속받음
Myvehicle??? 누구를 상속Car, Plane을 상속받음

이럴경우 또하나의 문제가 발생하는데

"업캐스팅" 문제이다.

다중 상속이 허용이 된다면 업캐스팅 문제가 발생함.

그래서 C#에서는 "다중 상속"을 지원하지 않는다.

인터페이스의 다중상속은 가능.

인터페이스는 내용이 아닌 외형을 물려주기 때문.

알아야할게 인터페이스는 "다중 상속"이 가능하기때문에

클래스명 : 인터페이스1, 인터페이스2

이런식으로 상속이 가능하다. 다만, 반드시 구현을 해야한다.

기본 구현 메소드

interface ILogger
{
	void WriteLog() {}
}

이 인터페이스 상속받는 애들은 무조건 다 구현을 해야됨.

여러개의 애들이 이것을 일단 다 구현을 해놨는데

ILogger인터페이스에 멤버 함수를 추가했다고 하자.

interface ILogger
{
	void WriteLog() {}
    void WriteLog2() {} // 추가한 함수
}

그러면 이거 상속받은 클래스들은 다 에러 뜬다.

구현부를 구현해주지 않아서 -> 일일히 다 수정 못함.

그럴때 사용하는것이 "기본 구현 메소드"이다.

interface ILogger
{
	void WriteLog() {}
    void WriteLog2(string error) 
    {
    	WriteLog(error);
    } // 추가한 함수
}

이렇게하면 ILogger를 상속받은 애들은 컴파일 에러 뜨지않는다.

추상 클래스

abstract

  • abstract 한정자는 클래스, 메서드, 프로퍼티, 인덱서, 이벤트와 함께 사용가능하다.
  • abstract가 사용되면 파생클래스에서 구현되어야 한다.
  • 추상 클래스 (abstract class)
  • 추상 클래스는 인스턴스화 될 수 없다.
  • 변수와 메서드 선언은 일반 클래스와 동일하게 할 수 있다. (물론 virtual도 사용가능)
  • 상속을 제한하는 sealed와는 같이 사용할 수 없다.
  • 추상 메서드 (abstract method)
  • 추상 메서드의 선언은 추상 클래스에서만 허용된다.
  • 추상 메서드는 암시적으로 가상(virtual) 함수이다.
  • 기본적으로 동작은 virtual 함수와 같지만, virtual과 달리 abstract는 파생 클래스에서 반- 드시 구현해야한다.
  • 추상 메서드는 구현부가 존재하지 않는다. ex) public abstract void test();
  • 파생 클래스에서는 동일한 시그니쳐 메서드에 override 키워드를 통해 재정의한다.
  • private, static, virtual 키워드와는 사용 불가능하다.

추상클래스나 클래스도 그 안에서 선언되는 모든 필드, 메소드, 프로퍼티 이벤트 등 모든 접근 한정자를 명시하지 않는다면,

priavate이다.

추상클래스는 abstract, public, private, protected, internal들의 한정자중 하나로 수식될 것을 강요한다.

연습 문제

연습문제 1. 인터페이스와 클래스가 다른 점은 무엇입니까?

풀이.

인터페이스는 클래스와 달리 내부에 메서드(함수)와 프로퍼티, 인덱서만 선언 가능하며, new 키워드를 통해 인스턴스화 할 수 없다. 또한 접근 지정자가 기본적으로 public으로 설정되어 있다. 따라서 해당 인터페이스를 상속받는 클래스를 만들어, 업 캐스팅 형식의 참조를 통해 인터페이스를 활용해야 한다.

나는 인터페이스를 약속이라고 생각한다. 인터페이스를 상속받는 모든 파생 클래스들은 인터페이스에 선언되어 있는 함수를 무조건 정의해야 한다. 따라서 어떤 프로그래머가 해당 클래스가 어떤 인터페이스를 상속받고 있는지만 알고 있어도, 해당 클래스가 어떤 기능을 하는지 유추할 수 있다.

위와 같은 점들이 인터페이스와 클래스의 큰 차이점이라고 생각한다.

연습문제 2. 인터페이스와 추상 클래스의 다른 점은 무엇입니까?

풀이.

추상클래스는 인터페이스와 기본적으로 역할(함수의 정의를 강요)은 비슷하지만, 인터페이스와 달리 데이터(변수)를 선언할 수 있다. 또한 필요에 의해 함수를 정의해도 괜찮다. 추상 클래스에는 해당 클래스에서만 사용 가능한 추상 메서드라는 것이 존재하는데, 이는 인터페이스의 메서드와 같은 역할을 한다. 하지만 모든 추상 클래스 내의 메소드와 데이터는 private으로 설정되어 있기 때문에, 추상 메서드의 접근 지정자를 public으로 설정하는 것을 추천한다.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글