문제

차별적 인 노조에서 왜 구속력이 허용되지 않습니까? 기본 생성자에서 BINDING이 실행되는 것과 관련이 있다고 가정합니까?

보조 메모에 다시 작성할 수있는 방법에 대한 제안 AI_Choose 감사하겠습니다. 가중 우선 순위를 AI와 함께 튜플로 유지하고 싶습니다. 내 생각은 가질 것입니다 AI_Weighted_Priority 상속 AI_Priority 재정의 선택. 나는 다른 길이의 지핑 목록을 다루고 싶지 않습니다 (나쁜 연습 IMO.)

open AI

type Condition =
    | Closest of float
    | Min
    | Max
    | Average
    member this.Select (aiListWeight : list<AI * float>) =
        match this with
        | Closest(x) -> 
            aiListWeight 
            |> List.minBy (fun (ai, priority) -> abs(x - priority))
        | Min -> aiListWeight |> List.minBy snd
        | Max -> aiListWeight |> List.maxBy snd
        | Average -> 
            let average = aiListWeight |> List.averageBy snd
            aiListWeight 
            |> List.minBy (fun (ai, priority) -> abs(average - priority))

type AI_Choose =
    | AI_Priority of list<AI> * Condition
    | AI_Weighted_Priority of list<AI * float> * Condition

    // I'm sad that I can't do this    
    let mutable chosen = Option<AI>.None

    member this.Choose() =
        match this with
        | AI_Priority(aiList, condition) -> 
            aiList 
            |> List.map (fun ai -> ai, ai.Priority())
            |> condition.Select
            |> fst
        | AI_Weighted_Priority(aiList, condition) -> 
            aiList 
            |> List.map (fun (ai, weight) -> ai, weight * ai.Priority())
            |> condition.Select
            |> fst

    member this.Chosen
        with get() = 
            if Option.isNone chosen then
                chosen <- Some(this.Choose())
            chosen.Value
        and set(x) =
            if Option.isSome chosen then
                chosen.Value.Stop()
            chosen <- Some(x)
            x.Start()

    interface AI with
        member this.Start() =
            this.Chosen.Start()
        member this.Stop() =
            this.Chosen.Stop()
        member this.Reset() =
            this.Chosen <- this.Choose()
        member this.Priority() =
            this.Chosen.Priority()
        member this.Update(gameTime) =
            this.Chosen.Update(gameTime)
도움이 되었습니까?

해결책

차별화 된 노조 내부에서 "구속력이 있도록"허용하는 것이 합리적입니다. 나는 그것이 불가능한 이유는 차별화 된 노조가 여전히 OCAML 디자인을 기반으로하고 물체는 .NET 세계에서 나오기 때문입니다. F# 은이 두 가지를 가능한 한 많이 통합하려고하지만 아마도 더 나아갈 수 있습니다.

어쨌든, 당신은 차별 조합을 사용하여 AI_Choose 유형. 이 경우 차별화 된 노조를 개별적으로 선언하고이를 사용하여 객체 유형을 구현할 수 있습니다.

나는 당신이 다음과 같은 글을 쓸 수 있다고 생각합니다.

type AiChooseOptions =
    | AI_Priority of list<AI> * Condition
    | AI_Weighted_Priority of list<AI * float> * Condition

type AiChoose(aiOptions) = 
    let mutable chosen = Option<AI>.None
    member this.Choose() =
        match aiOptions with
        | AI_Priority(aiList, condition) -> (...)
        | AI_Weighted_Priority(aiList, condition) -> (...)
    member this.Chosen (...)
    interface AI with (...)

클래스 계층 구조와 차별화 된 노조의 주요 차이점은 확장성에 관한 것입니다. 수업은 새로운 유형을 더 쉽게 추가 할 수있게되며 차별화 된 노조는 유형 (귀하의 경우 Aichooseoptions)에서 작동하는 새로운 기능을 더 쉽게 추가 할 수 있으므로 응용 프로그램을 설계 할 때 가장 먼저 고려해야 할 사항 일 수 있습니다.

다른 팁

관심있는 사람이라면 나는 파생을 끝내게했다 AI_Priority 그리고 AI_Weighted_Priority 추상 기본 클래스에서.

[<AbstractClass>]
type AI_Choose() =
    let mutable chosen = Option<AI>.None

    abstract member Choose : unit -> AI

    member this.Chosen
        with get() = 
            if Option.isNone chosen then
                chosen <- Some(this.Choose())
            chosen.Value
        and set(x) =
            if Option.isSome chosen then
                chosen.Value.Stop()
            chosen <- Some(x)
            x.Start()

    interface AI with
        member this.Start() =
            this.Chosen.Start()
        member this.Stop() =
            this.Chosen.Stop()
        member this.Reset() =
            this.Chosen <- this.Choose()
        member this.Priority() =
            this.Chosen.Priority()
        member this.Update(gameTime) =
            this.Chosen.Update(gameTime)

type AI_Priority(aiList : list<AI>, condition : Condition) =
    inherit AI_Choose()
    override this.Choose() =
        aiList 
        |> List.map (fun ai -> ai, ai.Priority())
        |> condition.Select
        |> fst

type AI_Weighted_Priority(aiList : list<AI * float>, condition : Condition) =
    inherit AI_Choose()
    override this.Choose() =
        aiList 
        |> List.map (fun (ai, weight) -> ai, weight * ai.Priority())
        |> condition.Select
        |> fst

이 코드를 다시 방문하면서 나는 Tomas의 제안을 받아 들였습니다.

type AiChooseOptions =
    | Priority of List<AI * Priority>
    | WeightedPriority of List<AI * Priority * float>
    member this.Choose(condition : Condition) =
        match this with
        | Priority(list) ->
            list 
            |> List.map (fun (ai, priority) -> ai, priority.Priority())
            |> condition.Select
        | WeightedPriority(list) ->
            list 
            |> List.map (fun (ai, p, weight) -> ai, p.Priority() * weight)
            |> condition.Select

type AiChoose(condition, list : AiChooseOptions ) =
    let mutable chosen = Unchecked.defaultof<AI>, 0.0

    interface AI with
        member this.Update(gameTime) =
            (fst chosen).Update(gameTime)

    interface Priority with
        member this.Priority() =
            chosen <- list.Choose(condition)
            (snd chosen)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top