VioletaBabel
3일차 본문
인터페이스
클래스와 비슷해보이나 메소드, 이벤트, 인덱서, 프로퍼티 만을 가질 수 있다.
모든 것이 public이며, 인스턴스를 만들 수 없다.
단, 클래스가 인터페이스를 상속받게 할 수 있으며 이런 경우엔 인터페이스에 선언된 모든 메소드 및 프로퍼티를 클래스에 구현해줘야한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace ConsoleApp1 { class Program { //인터페이스 이름 앞에 I를 붙이는게 관례 interface ILogger { void WriteLog(string log); } class ConsoleLogger : ILogger { // 콘솔로 출력 public void WriteLog(string message) { Console.WriteLine("{0} : {1}", DateTime.Now.ToLocalTime(), message); } } class FileLogger : ILogger { // 파일로 저장 private StreamWriter writer; public FileLogger(string path) { writer = File.CreateText(path); writer.AutoFlush = true; } public void WriteLog(string message) { writer.WriteLine("{0} : {1}", DateTime.Now.ToLocalTime(), message); } } class ClimateMonitor { private ILogger logger; public ClimateMonitor(ILogger logger) { this.logger = logger; } public void start() { while(true) { Console.Write("온도 : "); string temperature = Console.ReadLine(); if (temperature == "") break; logger.WriteLog("현재 온도 : "+temperature); } } } static void Main(string[] args) { ILogger l = new ConsoleLogger(); l.WriteLog("Hello, World!"); ClimateMonitor monitor = new ClimateMonitor(new FileLogger("MyLog.txt")); monitor.start(); } } } | cs |
인터페이스는 이처럼 자신에게로부터 파생될 클래스가 어떤 메소드를 구현해야 할 지를 정의한다.
인터페이스는 인터페이스를 상속받을 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | class Program { interface ILogger { void WriteLog(string log); } interface ILoggerPlus : ILogger { // 이제 이 인터페이스는 WriteLog라는 메소드를 두 개 가짐 void WriteLog(string format, params Object[] args); } class ConsoleLogger : ILoggerPlus { public void WriteLog(string message) { Console.WriteLine("{0} : {1}", DateTime.Now.ToLocalTime(), message); } public void WriteLog(string format, params Object[] args) { String message = String.Format(format, args); Console.WriteLine("{0} : {1}", DateTime.Now.ToLocalTime(), message); } } static void Main(string[] args) { ILoggerPlus l = new ConsoleLogger(); l.WriteLog("Hello, World!"); l.WriteLog("{0}+{1}={2}", 1, 2, 3); } } | cs |
인터페이스는 클래스와 달리, 여러 개의 인터페이스를 한꺼번에 상속받을 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class Program { interface IRun { void Run(); } interface IFly { void Fly(); } class Man : IRun, IFly //다중 상속 { public void Run() { Console.WriteLine("Run!"); } public void Fly() { Console.WriteLine("Fly!"); } } static void Main(string[] args) { Man m = new Man(); m.Run(); m.Fly(); IRun r = m as IRun; r.Run(); IFly f = m as IFly; f.Fly(); } } | cs |
추상 클래스 : 인터페이스와 달리 구현이 가능하나 클래스와 달리 인스턴스를 가질 수 없다.
인터페이스는 모든 메소드가 public인데 반해 추상 클래스는 클래스처럼 private이 디폴트다.
그리고 추상 메소드를 가질 수 있다.(인터페이스의 메소드처럼 상속 시 반드시 선언해야 한다는 약속의 역할을 한다.)
단, 추상 클래스가 다른 추상 클래스를 상속하는 경우 자식 추상 클래스는 부모 추상 클래스의 추상 메소드를 구현하지 않아도 된다. 다만 인스턴스를 생성할 클래스에서는 다 구현해야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | abstract class Base { protected void PrivateA() { Console.WriteLine("Base.PrivateA()"); } public void PublicA() { Console.WriteLine("Base.PublicA()"); } public abstract void AbstractA(); } class Derived : Base { public override void AbstractA() { Console.WriteLine("Derived.AbstractA()"); PrivateA(); } } static void Main(string[] args) { Base o = new Derived(); o.AbstractA(); o.PublicA(); } } | cs |
---
프로퍼티 : 편의성과 은닉성을 한 번에 만족하기 위한 것.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class MyClass { private int myField; public int MyField {//myField를 보호 get { return myField; } set { myField = value; } } } class Program { static void Main(string[] args) { MyClass m = new MyClass(); m.MyField = 10;//MyField를 사용한다. Console.WriteLine("{0}", m.MyField); } } | cs |
자동 구현 프로퍼티 : 프로퍼티를 더 간결하게 구현화하기 위한 것.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class MyClass { public int MyField { get; set; } } class Program { static void Main(string[] args) { MyClass m = new MyClass(); m.MyField = 10; Console.WriteLine("{0}", m.MyField); } } | cs |
프로퍼티 생성자 : 객체를 생성할 때 각 필드를 초기화하는 또 다른 방법
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class MyClass { public int MyField { get; set; } public string MyField2 { get; set; } } class Program { static void Main(string[] args) { MyClass m = new MyClass() {//콤마를 붙이고, 마지막엔 ;이 없다. MyField = 10, MyField2 = "a" }; Console.WriteLine("{0} , {1}", m.MyField, m.MyField2); } } | cs |
무명 형식
1 2 3 4 5 6 7 8 9 10 11 12 | class Program { static void Main(string[] args) { var a = new { Name = "Tom Riddle", Birth = 1926 }; Console.WriteLine("{0}, {1}", a.Name, a.Birth); var b = new { Events = "archery", Rank = new int[] { 1, 1, 3, 2 } }; Console.Write("{0} : ",b.Events); foreach (var rank in b.Rank) Console.Write("{0} ", rank); } } | cs |
인터페이스의 프로퍼티
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | interface IValue { string Name { get; set; } string NValue { get; set; } } class Value : IValue { public string Name { get; set; } public string NValue { get; set; } } class Program { static void Main(string[] args) { Value n = new Value() { Name = "qwerty", NValue = "Hi" }; Value m = new Value() { Name = "keyboard", NValue = "mouse" }; Console.WriteLine("{0} {1}", n.Name, n.NValue); Console.WriteLine("{0} {1}", m.Name, m.NValue); } } | cs |
추상 클래스의 프로퍼티
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | abstract class Pro { private static int id = 0; public string SerialID { get { return String.Format("{0:d5}", id++); } } abstract public DateTime Date { get; set; } } class RealPro : Pro { public override DateTime Date { get; set; } } class Program { static void Main(string[] args) { Pro p = new RealPro() { Date = new DateTime(2017, 1, 19) }; Console.WriteLine("{0}, {1}", p.SerialID, p.Date); Pro p2 = new RealPro() { Date = new DateTime(2018, 1, 19) }; Console.WriteLine("{0}, {1}", p2.SerialID, p2.Date); } } | cs |
Comments