추상 클래스

추상 클래스는 파생 클래스에서 구현을 제공할 수 있도록 일부 또는 모든 멤버를 구현하지 않은 상태로 두는 클래스입니다.

구문

// Abstract class syntax.
[<AbstractClass>]
type [ accessibility-modifier ] abstract-class-name =
[ inherit base-class-or-interface-name ]
[ abstract-member-declarations-and-member-definitions ]

// Abstract member syntax.
abstract member member-name : type-signature

설명

개체 지향 프로그래밍에서 추상 클래스는 계층 구조의 기본 클래스로 사용되며 다양한 개체 형식 집합의 일반적인 기능을 나타냅니다. "abstract"라는 이름에서 알 수 있듯이 추상 클래스는 종종 문제의 구체적인 엔터티에 직접 해당하지 않습니다기본. 그러나 여러 구체적인 엔터티의 공통점을 나타냅니다.

추상 클래스에는 특성이 AbstractClass 있어야 합니다. 멤버를 구현하고 구현하지 않았을 수 있습니다. 클래스에 적용할 때 추상이라는 용어의 사용은 다른 .NET 언어와 동일합니다. 그러나 메서드(및 속성)에 적용될 때 추상이라는 용어의 사용은 F#에서 다른 .NET 언어에서 사용하는 것과 약간 다릅니다. F#에서 메서드가 키워드(keyword) 표시 abstract 되면 멤버가 해당 형식에 대한 가상 함수의 내부 테이블에 가상 디스패치 슬롯이라고 하는 항목이 있음을 나타냅니다. 즉, 키워드(keyword) F#에서 사용되지 않지만 virtual 메서드는 가상입니다. 키워드(keyword) abstract 메서드 구현 여부에 관계 없이 가상 메서드에 사용 됩니다. 가상 디스패치 슬롯의 선언은 해당 디스패치 슬롯에 대한 메서드의 정의와는 별개입니다. 따라서 다른 .NET 언어의 가상 메서드 선언 및 정의에 해당하는 F#은 추상 메서드 선언과 키워드(keyword) 또는 override 키워드(keyword) 함께 별도의 정의 default 의 조합입니다. 자세한 내용 및 예제는 메서드를 참조 하세요.

클래스는 선언되었지만 정의되지 않은 추상 메서드가 있는 경우에만 추상으로 간주됩니다. 따라서 추상 메서드가 있는 클래스가 반드시 추상 클래스는 아닙니다. 클래스에 정의되지 않은 추상 메서드가 없는 경우 AbstractClass 특성을 사용하지 마세요.

이전 구문 에서 accessibility-modifierpublic또는 privateinternal. 자세한 내용은 Access Control을 참조하세요.

다른 형식과 마찬가지로 추상 클래스에는 기본 클래스와 하나 이상의 기본 인터페이스가 있을 수 있습니다. 각 기본 클래스 또는 인터페이스는 키워드(keyword) 함께 별도의 줄에 inherit 나타납니다.

추상 클래스의 형식 정의는 완전히 정의된 멤버를 포함할 수 있지만 추상 멤버를 포함할 수도 있습니다. 추상 멤버에 대한 구문은 이전 구문에서 별도로 표시됩니다. 이 구문에서 멤버의 형식 서명은 순서대로 매개 변수 형식과 반환 형식을 포함하는 목록이며, 토큰 및/또는 * 토큰으로 구분 -> 하여 커리 및 튜플 매개 변수에 적합합니다. 추상 멤버 형식 서명의 구문은 서명 파일에 사용되고 Visual Studio Code 편집기에서 IntelliSense가 표시하는 구문과 동일합니다.

다음 코드에서는 두 개의 비추상 파생 클래스인 Square 및 Circle이 있는 추상 클래스 Shape를 보여 줍니다. 이 예제에서는 추상 클래스, 메서드 및 속성을 사용하는 방법을 보여 줍니다. 예제에서 추상 클래스 Shape는 구체적인 엔터티 원과 정사각형의 공통 요소를 나타냅니다. 모든 셰이프(2차원 좌표계)의 공통 기능은 셰이프 클래스(그리드의 위치, 회전 각도, 영역 및 경계 속성)로 추상화됩니다. 위치를 제외하고 개별 셰이프의 동작을 재정의할 수 있습니다.

원 클래스에서와 같이 회전 메서드를 재정의할 수 있습니다. 이 클래스는 대칭으로 인해 회전이 고정됩니다. 따라서 Circle 클래스에서 회전 메서드는 아무 작업도 수행하지 않는 메서드로 대체됩니다.

// An abstract class that has some methods and properties defined
// and some left abstract.
[<AbstractClass>]
type Shape2D(x0: float, y0: float) =
    let mutable x, y = x0, y0
    let mutable rotAngle = 0.0

    // These properties are not declared abstract. They
    // cannot be overriden.
    member this.CenterX
        with get () = x
        and set xval = x <- xval

    member this.CenterY
        with get () = y
        and set yval = y <- yval

    // These properties are abstract, and no default implementation
    // is provided. Non-abstract derived classes must implement these.
    abstract Area: float with get
    abstract Perimeter: float with get
    abstract Name: string with get

    // This method is not declared abstract. It cannot be
    // overridden.
    member this.Move dx dy =
        x <- x + dx
        y <- y + dy

    // An abstract method that is given a default implementation
    // is equivalent to a virtual method in other .NET languages.
    // Rotate changes the internal angle of rotation of the square.
    // Angle is assumed to be in degrees.
    abstract member Rotate: float -> unit
    default this.Rotate(angle) = rotAngle <- rotAngle + angle

type Square(x, y, sideLengthIn) =
    inherit Shape2D(x, y)
    member this.SideLength = sideLengthIn
    override this.Area = this.SideLength * this.SideLength
    override this.Perimeter = this.SideLength * 4.
    override this.Name = "Square"

type Circle(x, y, radius) =
    inherit Shape2D(x, y)
    let PI = 3.141592654
    member this.Radius = radius
    override this.Area = PI * this.Radius * this.Radius
    override this.Perimeter = 2. * PI * this.Radius
    // Rotating a circle does nothing, so use the wildcard
    // character to discard the unused argument and
    // evaluate to unit.
    override this.Rotate(_) = ()
    override this.Name = "Circle"

let square1 = new Square(0.0, 0.0, 10.0)
let circle1 = new Circle(0.0, 0.0, 5.0)
circle1.CenterX <- 1.0
circle1.CenterY <- -2.0
square1.Move -1.0 2.0
square1.Rotate 45.0
circle1.Rotate 45.0
printfn "Perimeter of square with side length %f is %f, %f" (square1.SideLength) (square1.Area) (square1.Perimeter)
printfn "Circumference of circle with radius %f is %f, %f" (circle1.Radius) (circle1.Area) (circle1.Perimeter)

let shapeList: list<Shape2D> = [ (square1 :> Shape2D); (circle1 :> Shape2D) ]
List.iter (fun (elem: Shape2D) -> printfn "Area of %s: %f" (elem.Name) (elem.Area)) shapeList

출력:

Perimeter of square with side length 10.000000 is 40.000000
Circumference of circle with radius 5.000000 is 31.415927
Area of Square: 100.000000
Area of Circle: 78.539816

참고 항목