在F#中实现C#的IMatch接口并添加返回新实例的属性更新方法
F#类实现类似记录的更新方法问题解答
嗨,刚接触F#遇到这个问题太正常了——我当初也差点把类和记录的语法搞混😅
先理清楚问题出在哪:你写的Match是类类型,而那个能直接用{ this with ... }的Person是F#记录类型,这俩是完全不同的类型,记录的那个简洁更新语法只有记录能用,类是不支持的,所以编译器才会报错说找不到记录标签。
那怎么给类实现类似的更新方法呢?其实很简单,有两种方式可以选:
方法一:给类手动添加WithXXX方法
既然类不能用记录的语法,那我们就自己写方法,每次调用时把原有属性的值都传进去,只替换要更新的那个属性。比如给你的Match类加更新Finished和其他属性的方法:
type Match(competitionId: string, finished: bool, matchNumber: int, seriesType: SeriesType, matchType: MatchType) = interface IMatch with member this.Finished = finished member this.MatchNumber = matchNumber member this.SeriesType = seriesType member this.Type = matchType member this.CompetitionId = competitionId // 更新Finished状态的方法 member this.WithFinished newFinished = // 创建新的Match实例,传入原有属性,替换Finished的值 Match(this.CompetitionId, newFinished, this.MatchNumber, this.SeriesType, this.Type) // 更新MatchNumber的方法 member this.WithMatchNumber newNumber = Match(this.CompetitionId, this.Finished, newNumber, this.SeriesType, this.Type) // 同理,其他属性的更新方法依葫芦画瓢就行 member this.WithCompetitionId newId = Match(newId, this.Finished, this.MatchNumber, this.SeriesType, this.Type)
调用的时候就和记录的用法一样丝滑:
let originalMatch = Match("comp-001", false, 5, SeriesType.Cup, MatchType.Final) let completedMatch = originalMatch.WithFinished(true)
方法二:把Match改成记录类型(更推荐)
如果你的Match不需要复杂的类逻辑(比如可变状态、私有成员之类的),其实更推荐直接用F#记录类型来实现IMatch接口,这样就能直接用记录的原生更新语法,不用手动写一堆WithXXX方法,代码更简洁:
// 先定义记录类型 type Match = { CompetitionId: string Finished: bool MatchNumber: int SeriesType: SeriesType Type: MatchType } with // 实现IMatch接口 interface IMatch with member this.CompetitionId = this.CompetitionId member this.Finished = this.Finished member this.MatchNumber = this.MatchNumber member this.SeriesType = this.SeriesType member this.Type = this.Type
现在更新属性就和Person记录一样方便了:
let originalMatch = { CompetitionId = "comp-001"; Finished = false; MatchNumber = 5; SeriesType = SeriesType.Cup; Type = MatchType.Final } let updatedMatch = { originalMatch with Finished = true }
这种方式更符合F#的函数式编程风格,毕竟记录天生就是不可变的,和你的IMatch只读属性的语义完全匹配。
内容的提问来源于stack exchange,提问作者JOSEFtw
相关产品推荐
相关产品推荐

