728x90

인터페이스


1
2
3
4
interface ILogger // 첫글자 대문자로 적는건 약속
{
    
}
cs

인터페이스는 public

객체생성이 이뤄지지않는 껍데기


상속받은 자식클래스에서는 부모클래스에서 명시한 기능을 구현해야함

실제구현은 자식클래스

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Interface
{
    interface ICar
    {
        void drive(string msg);
    }
 
    interface IAirplane
    {
        void fly(string msg);
    }
 
    class Machine : ICar
    {
        public void drive(string msg)
        {
            Console.WriteLine(msg);
        }
    }
    class Machine2 : IAirplane
    {
        public void fly(string msg)
        {
            Console.WriteLine(msg);
        }
    }
    class MainApp
    {
        static void Main(string[] args)
        {
            Machine m1 = new Machine();
            Machine2 m2 = new Machine2();
        }
    }
}



죽음의 다이아몬드 

: c#에서 클래스 다중상속을 허용하지 않는 이유는 죽음의 다이아몬드 때문이다.

프로그램에서 같은 구문이 두 가지 이상의 의미로 해석될 여지가 있어서는 안 된다





하지만, 인터페이스를 사용하면 다중상속이 가능하다.


인터페이스를 사용하는 이유는 다음과 같다.

  • 자식단에서 구현할 메소드를 미리 구현
  • 메소드의 이름만 물려받고 자식클래스에서 재정의


IComparable 인터페이스

인터페이스는 모두 대문자 I 로 시작한다. IComparable 인터페이스는 비교할 때 사용되는 규약이다.

using System; using System.Collections; using System.Collections.Generic; namespace Study {     class Program     {         class Product         {             public string Name { getset; }             public int Price { getset; }             public override string ToString()             {                 return Name + " : " + Price + "원";             }         }               static void Main(string[] args)         {             List<Product> list = new List<Product>()             {                 new Product() {Name= "고구마", Price=1500},                 new Product() {Name= "사과", Price=2400},             };             list.Sort();             foreach(var item in list)             {                 Console.WriteLine(item);             }         }     } }


위의 프로그램은 Sort() 메서드가 정렬의 기준을 알지 못하기 때문에 오류가 발생한다. 이러한 기준을 정해주기 위해 IComparable 인터페이스를 구현한다.

해당 클래스에서 IComparable 인터페이스를 상속받아 사용한다.


IComparable에 커서를 놓고 Ctrl + .  단축키를 누르면 다음과 같이 인터페이스를 쉽게 구현할 수 있다. 



인터페이스 구현을 누르면 다음과 같이 CompareTo 메서드도 자동 생성된다.

public int CompareTo(object obj)
           {
               throw new NotImplementedException();
           }

CompareTo 메서드를 다음과 같이 변경해보자. obj가 Product이면 가격을 비교해 반환하겠다는 뜻이다. 오름차순으로 정렬된다.

public int CompareTo(object obj)
          {
              return this.Price.CompareTo((obj as Product).Price);
          }


내림차 순으로 정렬하고 싶다면 다음과 같이 변경하면 될 것이다.

public int CompareTo(object obj)
{
    return (obj as Product).Price.CompareTo(this.Price);
}


using 키워드와 IDisposable 인터페이스


아래 예제에서는 IDisposable 인터페이스를 상속받은 클래스 Dummy의 인스턴스를 using 블록의 괄호 내에서 생성한다.

Dispose() 메서드를 따로 호출하지 않아도 using 블록을 벗어날 때 호출된다.

using System;

namespace Study
{
    class Program
    {
        class Dummy : IDisposable
        {
            public void Dispose()
            {
                Console.WriteLine("Dispose() 메서드 호출");
            }
        }


        static void Main(string[] args)
        {
            using (Dummy dummy = new Dummy())
            {
 
            }
        }
    }
}



파일 입출력

using System.IO;

파일을 쓸 때 사용하는 StreamWriter는 IDisposable 인터페이스를 구현한 대표적인 클래스이다.


아래 파일 입출력 경로를 보면 @ 기호가 쓰인 것을 볼 수 있다.

문자열 내부에서 \ 기호는 특수한 의미를 지니기 때문에 원래는 \\를 사용해야 한다.


하지만 @ 기호를 붙여 문자열을 만들면 \\기호를 여러번 쓰지않아도 된다. 다만 내부에서 이스케이프 문자를 사용할 수 없게 된다.


using System;
using System.IO;
 
namespace Study
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = @"c:\tesst\test.txt";
            string textValue = "시간 - " + DateTime.Now;
 
            try
            {
                File.WriteAllText(path, textValue);
                Console.WriteLine("읽은 문자열 : " + File.ReadAllText(path));        
            }
            catch (Exception)
            {
 
                Console.WriteLine("파일을 읽거나 쓸 수 없습니다");
            }
        }
    }
}


스트림으로 쓰기


큰 용량의 파일을 한꺼번에 읽고 쓰는 것은 시스템에 부담이 가기 때문에 파일을 한 줄씩 읽고 쓸 수 있는 다양한 방법이 있다.

StreamWrite 클래스를 이용하면 스트림으로 쓸 수 있다.


StreamWrite 클래스는 TextWriter의 상속을 받는다.

// 요약:
//     System.IO.TextWriter를 구현하여 특정 인코딩의 스트림에 문자를 씁니다.
[Serializable]
[ComVisible(true)]
public class StreamWriter : TextWriter


TextWriter는 abstract class로 MarshalByRefObject, IDisposable의 상속을 받는다.

이를 통해 IDisposable 인터페이스를 구현한 클래스라는 것을 알 수 있다.

public abstract class TextWriter : MarshalByRefObjectIDisposable


다음은 StreamWrite 클래스로 파일에 여러 문자열을 쓰는 예제이다.

static void Main(string[] args)
        {
            string path = @"c:\test\test.txt";
 
            using (StreamWriter writer = new StreamWriter(path))
            {
                writer.WriteLine("안녕");
                writer.WriteLine("여러줄을");
                writer.WriteLine("입력해봄");
            }
 
            Console.WriteLine(File.ReadAllText(path));
        }



StreamReader 클래스로 한줄씩 읽기


아래는 잘못된 예제이다. 한 줄을 읽고 따로 값이 저장되지 않았기에 2번째 줄만 출력된다.

class Program
    {
        static void Main(string[] args)
        {
            string path = @"c:\test\test.txt";
 
            using (StreamReader reader = new StreamReader(path))
            {
                while (reader.ReadLine() != null)
                {                    
                    Console.WriteLine(reader.ReadLine());
                }
            }
        }
    }

바른 예

static void Main(string[] args)
        {
            string path = @"c:\test\test.txt";
 
            using (StreamReader sr = new StreamReader(path))
            {
                while (sr.Peek() >= 0)
                {
                    Console.WriteLine(sr.ReadLine());
                }
            }
        }


using을 사용하지 않은 예

class Program
{
    static void Main(string[] args)
    {
        string path = @"c:\test\test.txt";
 
        StreamReader reader = new StreamReader(path);
        string line;
 
        while ((line = reader.ReadLine()) != null)
                Console.WriteLine(line); 
    }
}


인터페이스, 내용 정리


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

public class MyConnection : Component, IDbConnection, IDisposable
{
}


인스턴스 변수를 가질 수 없다.

오류 : 인터페이스 멤버에는 정의를 사용할 수 없습니다.

interface IBasic
        {
            void TestMethod()
            {
 
            }
        }

인터페이스는 인스턴스 메서드를 가질 수 있다.


인터페이스는 클래스 변수를 가질 수 없다.

인터페이스는 클래스 메서드를 가질 수 없다.


인터페이스는 속성(Property)을 가질 수 있다.

'Study > C#' 카테고리의 다른 글

C# 네트워크 기본  (1) 2017.04.12
C# 예외처리, delegate  (0) 2017.04.10
C# 클래스, 메소드  (0) 2017.04.04
c# 복습  (0) 2017.03.31
headfirst c#-wpf  (0) 2016.11.19

+ Recent posts