요약 C#


추상
이것은 소프트웨어 개발에서 매우 유용한 것 중의 하나이며, 결코 유일한 것이 아니다.NET는 어떤 사물을 추상적으로 하는 능력이다.예컨대 커피.(만약 당신이 나의 다른 블로그와 함께 이곳을 주목한다면, 당신은 사람을 불안하게 하는 추세에 주의할 수 있을 것이다.)대부로 명명된 유명 회사와 소스 케이크가 이런 신기한 음료를 팔고 있다.너는 설탕을 넣은 것을 마실 수 있지만, 나는 직접 마시는 것을 좋아한다.모든 이 상점들은 자신만의 독특한 음료를 가지고 있지만, 그것들은 모두 커피라고 불린다.캐러멜 마지아토는 기능상 이중 아메리카노와 다르지만 왠지'커피'라는 더 거대한 범주에 속하기 때문이다.
소프트웨어 개발에서 우리는 추상이라고 부른다.대상 프로그래밍에서 우리는 그것과 상호작용하고 코드에 저장된 데이터를 대상으로 삼을 것이다.그러나 이런 속기는 현실 세계와 별도로 비슷한 점이 있다.들어와.NET에는 두 가지 유형의 추상이 있습니다.추상적인 승차순에 따라 (이것은 완전히 하나의 단어이지만 찾지 마라.)너는 구체적인 종류, 추상적인 종류와 인터페이스가 있다.
통상적으로 말하는 구체적인 유형에서 사물의 세부 사항은 사물 자체와 내재적인 관계를 가진다.당신의 핸드폰을 예로 들면 모든 핸드폰이 같은 앱, 같은 코드와 같은 기능을 가진 세계를 상상해 보세요.이것은 좀 지루할 수 있지만, 적어도 우리는 안심할 수 있다. 빌어먹을 것은 쉽게 대체될 것이다.
현재 추상류는 할 수 있는 생각과 행위의 집합이지만 필요하면 과도하게 쓴다는 것을 구체적으로 나타낸다.다시 핸드폰을 사용할 때 핸드폰 대상이 문자로 메시지를 보낼 수 있다. 이 대상은 IMessages(파란색 거품 연합!)라는 기이한 물건으로 메시지를 덮어쓰고 발송한다.또 하나는 메시지라는 것으로 이 기능을 덮어쓰는 것이다. (기술적으로는 더 좋은 실현이지만, 그것을 사용하는 사람이 있습니까?)이러한 추상화를 통해 메시지 전달 응용 프로그램은 특정한 스타일과 결합하여 기본 옵션을 사용할 수 있다.예를 들면 다음과 같습니다.
public abstract class CellPhone
{
    public virtual void SendMessage()
    {
        Console.WriteLine("SMS Sent");
    }
}

public class FruitPhone : CellPhone
{
    public override void SendMessage()
    {
        Console.WriteLine("Fancy message sent with a blue bubble, how fancy.");
        base.SendMessage();
    }
}

public class RobotPhone : CellPhone
{
    public override void SendMessage()
    {
        Console.WriteLine("Sent RCS Message with awesome features");
        base.SendMessage();
    }
}
본질적으로, 우리가 여기서 하는 것은 세 개의 서로 다른 장치가 같은 기능을 처리하도록 하는 것이지만, 표준화된 기본 프로토콜을 사용하는 반환 방식은 다소 다르다.휴대전화가 필요한 물건이 있으면 과일 휴대전화나 로봇 휴대전화를 보내면 SendMessage() 방법을 사용할 수 있기 때문에 매우 편리하다.그래서 현실적으로 만약에 메시지를 보내는 방법이 있다면 이렇게 핸드폰 요약을 받을 것이다.
SendMessage(CellPhone phone)
{
    phone.SendMessage();
}
그것은 메시지를 보내기 위해 휴대전화나 로봇 휴대전화가 필요하다.휴대전화는 정보를 어떻게 보내는지 알아야 하는 유일한 물건이다.이러한 추상적인 단계를 정의 대상의 수단으로 간주하고 모든 가능한 실현에서 일부 핵심 기능을 공유해야 한다.
이제 내가 가장 좋아하는 인터페이스를 보자.인터페이스는 매우 편리하지만, 그것들은 더 많은 일을 필요로 한다.그것들은 추상적인 차원으로 그것을 계승하는 어떤 것도 모든 것을 실현해야 한다.일종의 실천으로 삼다.NET의 접두사는 코드에서 찾을 수 있도록 i입니다.지난번 커피 제작 프로젝트를 살펴보고 그 중 일부를 간소화하기 시작하자.

왜 추상적
추상은 당신의 삶을 더욱 가볍게 한다. 특히 우리가 커피를 끓이는 방법을 창조했기 때문이다.추상적인 흥미로운 점은 그것을 사용하는 데 필요한 정보량을 줄일 수 있다는 것이다.이전 블로그에서 본 스위치의 작동 방식:
switch (coffeeType)
{
    case BrewStyle.FrenchPress:
        var press = new FrenchPress();
        press.Brew();
        press.Press();
        press.Pour();
        break;
    case BrewStyle.PodSystem:
        var pod = new PodSystem();
        pod.Brew();
        pod.Pour();
        break;
}
나는 이 일에 대해 위축감을 느낀다. 이것은 내가 쓴 것이다.만약 우리가 새로운 커피 종류를 추가해야 한다면, 우리는 그것을 처리하기 위해 여기를 변경해야만 할 것이다.또한 PodSystem에 단계를 추가해야 할 경우 이를 변경해야 합니다.야야야.소프트웨어 개발에서 이를 '결합' 이라고 부르는 것은 허용되지 않는다. 가능하다면 코드에서 이런 상황이 발생하는 것을 피하십시오. 왜냐하면 이런 일들을 장기적으로 추적하는 것은 어렵고 시간이 걸리며 곤혹스러울 수 있기 때문입니다.나는 어려움을 받아들이고 싶지만, 곤혹과 시간 소모는 절대로 내가 다른 사람이 하기를 바라는 일이 아니기 때문에, 우리가 나의 잘못을 수습하자.

Short hand of "knowledge"
I forget where I picked this up, but the way I like to think about the usefulness of abstraction comes down to "knowledge". The more one piece of code needs to know about how another piece of code operates, the more dependent or coupled they are. This coupling increases complexity and changing things becomes more difficult as systems grow. I will keep using this terminology, because it's been very helpful to me in thinking through how to work on these sorts of problems.


우선, 따라가는 경우 계속해서 Brew 폴더로 이동하여 Coffee라는 새 파일을 만듭니다.대테러 엘리트.
cd Brew
touch Coffee.cs
cd ..
code .
현재 목표는 플러그인 클래스를 brewing 클래스에서 옮기는 것입니다.응용 프로그램의 다양한 측면에서 무엇을 알아야 하는지를 감안하여 brew를 알 수 없는 것으로 설정하고자 합니다. 프랑스 미디어, 팟캐스트 시스템을 처리할 수 있고, 우리가 만들고 싶은 새로운 커피까지 받을 수 있으며, 양조기 업데이트를 걱정할 필요가 없습니다.우선, 우리 커피를 열어봅시다.
우선, 브루스터 스타일의 매거진을 이 파일로 옮깁시다.하나 더 추가합시다.
public enum BrewStyle
{
    FrenchPress, PodSystem, FrisbeeBrew
}

public enum Granularity
{
    Fine = 0, KindaFine = 1, Medium = 3, KindaCoarse = 4, Coarse = 5, Chunky = 6, WholeBean = 7
}
만약 우리가 계속 구체적인 과정에 의존한다면, 플라잉 맥주를 첨가하는 것이 마지막 볏짚이 될 것이다.그래서 우리는 모든 것의 표시를 쓰고 인터페이스를 사용할 것이다.
public interface iCoffee
{
    int Temperature { get; set; }
    BrewStyle Style { get; }
    Granularity GrindGranularity { get; set; }
    iCoffee Brew();
    iCoffee Pour();
}
인터페이스를 사용하면 클래스가 어떤 속성을 가지고 응용 프로그램이 어떤 조작을 할 수 있는지 정의할 수 있습니다.이런 상황에서 우리의 모든 커피는 Brew()Pour()의 설명이 있다.관례에 따르면 인터페이스의 명칭 앞에는 i이 있다.또한 Temperature의 속성을 제시했습니다.
이제 우리 프랑스 매체를 재구성하자.
public class FrenchPress : iCoffee
{
    public int Temperature { get; set; } = 70;
    public BrewStyle Style => BrewStyle.FrenchPress;
    public Granularity GrindGranularity { get; set; } = Granularity.WholeBean;
    public iCoffee Brew()
    {
        BoilWater();
        GrindBeans();
        WaitAMinute();
        return this;
    }

    private void WaitAMinute()
    {
        for (int i = 0; i < 100; i++)
            Write($"\r{GetChar(i)}  ");
        Console.WriteLine();
    }

    private char GetChar(int position) =>
        (position % 4) switch
        {
            0 => '|',
            1 => '/',
            2 => '-',
            3 => '\\'
        };

    private void GrindBeans()
    {
        Console.WriteLine("Grinding beans.");
        while (GrindGranularity != Granularity.KindaCoarse)
            Write($"\rCurrent granularity: {--GrindGranularity}.");

        Console.WriteLine();
    }
    private void BoilWater()
    {
        Console.WriteLine("Boiling water.");
        while (Temperature < 200)
            Write($"\rCurrent temperature is {++Temperature}°F.");
        Console.WriteLine();
    }

    private void Write(string line)
    {
        Console.Write(line);
        System.Threading.Thread.Sleep(100);
    }

    public iCoffee Pour()
    {
        Console.WriteLine("Pouring.");
        Console.WriteLine("Enjoy!");
        return this;
    }
}
여기에 주의해야 할 몇 가지 일이 있다.우선, 클래스 정의는 :을 첨부했다.이는 C#에서 몇 가지를 의미하며 특히 "실현"을 의미합니다.전체적으로 :위는'상속'을 의미하지만 인터페이스에 대해서는 상속할 것이 없다.C#에 대해 우리는 일반적으로 상속을 미리 정의된 기능을 가져와 다른 종류에 적용하는 방법으로 사용하거나 추상적인 상황에서 미리 정의된 기능을 사용해서 다시 쓰기를 선택할 수 있다.인터페이스에서 계승할 때 이런 일반적인 묘사 외에 계승할 수 있는 것이 없기 때문에 더욱 흔히 볼 수 있는 말은'이루다'이다.
방법 Brew()은 이미 몇 가지 내부 방법을 사용하는데 마치 Pour()과 같다.전에 말씀드렸던'알아요'기억나세요?이런 방법을 사용하면'public'로 표시된 모든 것이 우리의 코드를 사용하는 사람들이 알아야 할 것으로 확정된다.이런 상황에서 인터페이스는 커피의 온도를 알고 BrewPour을 커피에 어떻게 첨가하는지 알아야 한다고 밝혔다.또 다른 거 있어요?외부 코드와는 무관합니다.우리는 카페 내부에서만 개인 서비스를 제공한다.
이 파일에 다른 두 종류의 커피를 추가해서 우리가 어떻게 이런 인터페이스 기술을 사용해서 우리의 양조 시스템을 더욱 깨끗하게 하는지 봅시다.
public class PodSystem : iCoffee
{
    public int Temperature { get; set; }
    public BrewStyle Style => BrewStyle.PodSystem;
    public Granularity GrindGranularity { get; set; } = Granularity.KindaFine;
    public iCoffee Brew()
    {
        InsertPod();
        PushButton();
        return this;
    }

    private void InsertPod()
    {
        Console.WriteLine("Inserting pod.");
    }

    private void PushButton()
    {
        Console.WriteLine("Button pressed.");
        Console.WriteLine("Waiting for coffee.");
        Console.WriteLine("Done.");
    }

    public iCoffee Pour()
    {
        return this;
    }
}

public class FrisbeeBrew : iCoffee
{
    public int Temperature { get; set; } = 70;
    public BrewStyle Style => BrewStyle.FrisbeeBrew;
    public Granularity GrindGranularity { get; set; } = Granularity.WholeBean;
    public iCoffee Brew()
    {
        BoilWater();
        GrindBeans();
        Console.WriteLine("Stirring.");
        Stir();
        WaitAMinute();
        return this;
    }

    private void Write(string line)
    {
        Console.Write(line);
        System.Threading.Thread.Sleep(100);
    }
    private void BoilWater()
    {
        Console.WriteLine("Boiling water.");
        while (Temperature < 200)
            Write($"\rCurrent temperature is {++Temperature}°F.");
        Console.WriteLine();
    }
    private void GrindBeans()
    {
        Console.WriteLine("Grinding beans.");

        while (GrindGranularity != Granularity.Fine)
            Write($"\rCurrent granularity: {--GrindGranularity}.".PadRight(50));

        Console.WriteLine();
    }

    private void Stir()
    {
        for (int i = 0; i < 50000; i++)
            Console.Write($"\r{GetChar(i)}  ");

        Console.WriteLine();
    }

    private void WaitAMinute()
    {
        for (int i = 0; i < 100; i++)
            Write($"\r{GetChar(i)}  ");

        Console.WriteLine();
    }

    private char GetChar(int position) =>
        (position % 4) switch
        {
            0 => '|',
            1 => '/',
            2 => '-',
            3 => '\\'
        };
    public iCoffee Pour()
    {
        Console.WriteLine("Pouring.");
        return this;
    }
}
현재, 당신이 판단하기 전에, 우리는 잠시 후에 복사하고 붙여넣은 코드를 토론할 것입니다.지금 중요한 것은 우리가 현재 세 가지 다른 종류가 같은 인터페이스를 실현하지만 다른 일을 하고 있다는 것이다.
이제 우리는 도대체 그것을 어떻게 사용해야 합니까?인터페이스에 대한 나의 첫 번째 직감은 다음과 같이 구체적인 실례를 다시 만들고 인터페이스를 사용하는 변수에 분배하는 것이다.
iCoffee coffee = new FrenchPress();
이것은 완전히 옳다. 물론 나쁜 일도 아니다.많은 곳에서, 너는 이렇게 할 수 있지만, 우리의 목적에서 우리는 공장 모델을 사용할 것이다.이것은 우리가 필요할 때 우리가 필요로 하는 물건을 만들어 내는 것을 허락할 것이다.
cd Brew
touch CoffeeFactory.cs
cd ..
커피 공장을 열다.다음을 추가합니다.
using System;
using System.Collections.Generic;
using System.Linq;

namespace Brewing
{
    public class CoffeeFactory
    {
        public static List<iCoffee> coffees = new List<iCoffee>();
        internal static iCoffee Create(BrewStyle coffeeType)
        {
            if (!coffees.Exists(coffee => coffee.Style == coffeeType))
                coffees.Add(CoffeeSwitch(coffeeType));

            return coffees.First(coffee => coffee.Style == coffeeType);
        }

        internal static iCoffee CoffeeSwitch(BrewStyle coffeeType) =>
            coffeeType switch
            {
                BrewStyle.FrenchPress => new FrenchPress(),
                BrewStyle.PodSystem => new PodSystem(),
                BrewStyle.FrisbeeBrew => new FrisbeeBrew()
            };
    }
}
우리는 우리가 필요로 하는 브루스터 스타일을 받아들이기 위해 정적 공장을 만들고 있다.간단하게 보기 위해서, 우리는 커피 목록을 사용하여, 모든 종류의 커피가 우리의 커피 양조업자에게 한 잔만 제공되도록 확보한다.우리는 먼저 필요한 브루스터 스타일의 커피가 있는지 검사했다.만약 없다면, 우리는 커피 스위치를 우리에게 새로운 것으로 목록에 추가한 다음, 브루스텔의 정확한 커피로 돌아가도록 요구한다.좋고 깨끗해요.그리고 만약 우리가 커피를 더 많이 첨가해야 한다면, 우리는 그것을 선택으로 첨가해야 할 곳이 있다.
이제 Brew로 돌아가야 합니다.cs와 더 많은 일을 합니다.개인적으로 가장 좋아하는 작품들가능한 한 많이 삭제해라.
public class Brew : System.CommandLine.Command
{
    public Brew(string name, string description = null) : base(name, description)
    {
        Add(new Option<BrewStyle>("--coffeeType"));
        Handler = CommandHandler.Create<BrewStyle>(BrewCoffee);
    }

    public void BrewCoffee(BrewStyle coffeeType)
    {
        var coffee = CoffeeFactory.Create(coffeeType);
        coffee.Brew();
        coffee.Pour();
    }
}
이거 봐.이제 우리는 다양한 종류의 커피를 첨가할 수 있지만 양조 메커니즘은 바뀌지 않는다.커피를 어떻게 끓이는지 모르기 때문에, 이 지식들은 모두 커피 수업에 저장되어 있기 때문에, 그것은 이렇게 할 필요가 없다.그것은 심지어 그것이 어떤 종류의 커피인지 알 필요가 없다. 우리의 스위치는 지금 없어졌다.BrewCoffee 방법은 CLI 구현에서 데이터를 얻어 알 수 없는 방식으로 BrewCoffee() 방법에 전달하고, 프랑스 출판사, PodSystem 또는 Frisbee에 대한 어떠한 정보도 알지 못하는 상황에서 Brewing은 각각의 변화를 진행한다.
우리 빠르게 우리의 프로그램을 살펴보자.대테러 엘리트:
static void Main(string[] args)
{
    var rootCommand = new RootCommand() { new Brewing.Brew("brew") };
    rootCommand.InvokeAsync(args).Wait();
}
이제 테스트해 봅시다.이 설정을 사용하면 dotnet CLI 를 사용하여 애플리케이션을 테스트할 수 있습니다.
dotnet run -- brew --coffeeType FrenchPress
이것은 프랑스 매체를 만들었다.다른 커피를 시도해 봅시다.
dotnet run -- brew --coffeType PodSystem
마지막으로 새로운 커피를 시도해 봅시다. 플라잉 디스크 타기!
dotnet run -- brew --coffeeType FrisbeeBrew

쿨, 커피?
네, 커피와 공장입니다.만약 네가 나와 같다면, 이 작품들을 모두 함께 쓰는 것을 보면 도움이 될 것이다.예제를 보려면 github으로 전화하십시오.만약 그것을 고치고 확장하고 싶다면, 현지에서 마음대로 갈라지거나 복제할 수 있다.
원하는 변경 사항이나 확장을 알 수 있도록 아래에서 소리를 내십시오.깨끗이 씻고 싶으세요?부탁 하나 해주세요!시스템에 더 많은 도구가 있는지 궁금하다.명령행?나도!이것은 다음 의사일정이다.

좋은 웹페이지 즐겨찾기