인터페이스(F#)

인터페이스는 다른 클래스가 구현하는 관련 멤버 집합을 지정합니다.

구문

// Interface declaration:
[ attributes ]
type [accessibility-modifier] interface-name =
    [ interface ]     [ inherit base-interface-name ...]
    abstract member1 : [ argument-types1 -> ] return-type1
    abstract member2 : [ argument-types2 -> ] return-type2
    ...
[ end ]

// Implementing, inside a class type definition:
interface interface-name with
    member self-identifier.member1argument-list = method-body1
    member self-identifier.member2argument-list = method-body2

// Implementing, by using an object expression:
[ attributes ]
let class-name (argument-list) =
    { new interface-name with
        member self-identifier.member1argument-list = method-body1
        member self-identifier.member2argument-list = method-body2
        [ base-interface-definitions ]
    }
    member-list

설명

인터페이스 선언은 구현된 멤버가 없다는 점을 제외하고 클래스 선언과 유사합니다. 대신 모든 멤버는 키워드(keyword) abstract표시된 대로 추상적입니다. 추상 메서드에 대한 메서드 본문은 제공하지 않습니다. F#은 인터페이스에서 기본 메서드 구현을 정의할 수 없지만 C#에서 정의한 기본 구현과 호환됩니다. 키워드(keyword) 사용하는 default 기본 구현은 비 인터페이스 기본 클래스에서 상속하는 경우에만 지원됩니다.

인터페이스의 기본 접근성은 .입니다 public.

필요에 따라 기본 F# 구문을 사용하여 각 메서드 매개 변수에 이름을 지정할 수 있습니다.

type ISprintable =
    abstract member Print: format: string -> unit

위의 ISprintable 예제 Print 에서 메서드에는 이름이 format있는 형식 string 의 단일 매개 변수가 있습니다.

인터페이스를 구현하는 방법에는 개체 식을 사용하고 형식을 사용하는 두 가지 방법이 있습니다. 두 경우 모두 형식 또는 개체 식은 인터페이스의 추상 메서드에 대한 메서드 본문을 제공합니다. 구현은 인터페이스를 구현하는 각 형식에 따라 다릅니다. 따라서 다른 형식의 인터페이스 메서드는 서로 다를 수 있습니다.

정의의 시작과 end끝을 표시하는 키워드(keyword) interface 및 간단한 구문을 사용하는 경우 선택 사항입니다. 이러한 키워드(keyword) 사용하지 않는 경우 컴파일러는 사용하는 구문을 분석하여 형식이 클래스인지 인터페이스인지 유추하려고 시도합니다. 멤버를 정의하거나 다른 클래스 구문을 사용하는 경우 형식은 클래스로 해석됩니다.

.NET 코딩 스타일은 모든 인터페이스를 대문 I자로 시작하는 것입니다.

F#스타일 및 .의 두 가지 방법으로 여러 매개 변수를 지정할 수 있습니다. NET 스타일입니다. 둘 다 .NET 소비자에 대해 동일한 방식으로 컴파일되지만 F#스타일은 F# 호출자가 F#스타일 매개 변수 애플리케이션 및 를 사용하도록 강제합니다. NET 스타일은 F# 호출자가 튜플 인수 애플리케이션을 사용하도록 강제합니다.

type INumericFSharp =
    abstract Add: x: int -> y: int -> int

type INumericDotNet =
    abstract Add: x: int * y: int -> int

클래스 형식을 사용하여 인터페이스 구현

다음 코드와 같이 키워드(keyword), 인터페이스 이름 및 with 키워드(keyword) 다음 인터페이스 멤버 정의를 사용하여 interface 클래스 형식에서 하나 이상의 인터페이스를 구현할 수 있습니다.

type IPrintable =
    abstract member Print: unit -> unit

type SomeClass1(x: int, y: float) =
    interface IPrintable with
        member this.Print() = printfn "%d %f" x y

인터페이스 구현은 상속되므로 파생 클래스를 다시 구현할 필요가 없습니다.

호출 인터페이스 메서드

인터페이스 메서드는 인터페이스를 구현하는 형식의 개체를 통하지 않고 인터페이스를 통해서만 호출할 수 있습니다. 따라서 이러한 메서드를 호출하기 위해 연산자 또는 upcast 연산자를 사용하여 :> 인터페이스 형식으로 업캐스트해야 할 수 있습니다.

형식 SomeClass의 개체가 있을 때 인터페이스 메서드를 호출하려면 다음 코드와 같이 개체를 인터페이스 형식으로 업캐스트해야 합니다.

let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()

다른 방법은 다음 예제와 같이 인터페이스 메서드를 업캐스트하고 호출하는 개체에서 메서드를 선언하는 것입니다.

type SomeClass2(x: int, y: float) =
    member this.Print() = (this :> IPrintable).Print()

    interface IPrintable with
        member this.Print() = printfn "%d %f" x y

let x2 = new SomeClass2(1, 2.0)
x2.Print()

개체 식을 사용하여 인터페이스 구현

개체 식은 인터페이스를 구현하는 간단한 방법을 제공합니다. 명명된 형식을 만들 필요가 없고 추가 메서드 없이 인터페이스 메서드를 지원하는 개체만 원할 때 유용합니다. 개체 식은 다음 코드에 설명되어 있습니다.

let makePrintable (x: int, y: float) =
    { new IPrintable with
        member this.Print() = printfn "%d %f" x y }

let x3 = makePrintable (1, 2.0)
x3.Print()

인터페이스 상속

인터페이스는 하나 이상의 기본 인터페이스에서 상속할 수 있습니다.

type Interface1 =
    abstract member Method1: int -> int

type Interface2 =
    abstract member Method2: int -> int

type Interface3 =
    inherit Interface1
    inherit Interface2
    abstract member Method3: int -> int

type MyClass() =
    interface Interface3 with
        member this.Method1(n) = 2 * n
        member this.Method2(n) = n + 100
        member this.Method3(n) = n / 10

기본 구현을 사용하여 인터페이스 구현

C#은 다음과 같이 기본 구현을 사용하여 인터페이스 정의를 지원합니다.

using System;

namespace CSharp
{
    public interface MyDim
    {
        public int Z => 0;
    }
}

F#에서 직접 사용할 수 있습니다.

open CSharp

// You can implement the interface via a class
type MyType() =
    member _.M() = ()

    interface MyDim

let md = MyType() :> MyDim
printfn $"DIM from C#: %d{md.Z}"

// You can also implement it via an object expression
let md' = { new MyDim }
printfn $"DIM from C# but via Object Expression: %d{md'.Z}"

가상 멤버를 재정의하는 것과 같이 기본 구현 override을 재정의할 수 있습니다.

기본 구현이 없는 인터페이스의 모든 멤버는 여전히 명시적으로 구현되어야 합니다.

다른 제네릭 인스턴스화에서 동일한 인터페이스 구현

F#에서는 다음과 같이 다른 제네릭 인스턴스화에서 동일한 인터페이스를 구현할 수 있습니다.

type IA<'T> =
    abstract member Get : unit -> 'T

type MyClass() =
    interface IA<int> with
        member x.Get() = 1
    interface IA<string> with
        member x.Get() = "hello"

let mc = MyClass()
let iaInt = mc :> IA<int>
let iaString = mc :> IA<string>

iaInt.Get() // 1
iaString.Get() // "hello"

참고 항목