在下文中,我定义Animator
的方式在OOP系统中很常见,可以认为改变this
对象的状态是正确的:
type MyViewController() =
inherit UIViewController()
//Is there a better way than this?
member val Animator = null with get, set
override this.ViewDidLoad() =
base.ViewDidLoad()
//this.View is defined in base class and is only valid *now*
this.Animator <- new UIDynamicAnimator(this.View)
是否有更惯用的方式来定义Animator
进行通信:&#34; null
- &gt;对象正常,对象 - &gt;对象被禁止&#34;?
(显然,我可以编写一个在运行时检查和抛出的自定义set
函数,但这似乎更令人讨厌,而且非常有用而且非常有用。)
答案 0 :(得分:4)
一旦库非常依赖继承,即使你使用F#,也很难避免通常的OO模式。所以公平地说,我可能会编写与您所做的完全相同的代码,并且只是考虑到这部分代码不会那么漂亮(并且在应用程序的某些部分中使用更多功能方法)没有被框架强制进入OO风格)。
另外,在这种情况下,我只使用null
- 您可以使用option
,但是您没有获得任何好处,因为如果值为{,您将无法做多少工作{1}}无论如何。
据推测,在您的完整源代码中,您将覆盖该类的其他方法,并且您正在创建None
,以便可以在其他方法中使用它。你可以做的一件事是从类中提取代码并编写如下代码:
Animator
这里的想法是type IInitializedView =
abstract OtherMethod : UIViewController -> unit
type MyViewController(viewInitialized:UIView -> IInitializedView) =
inherit UIViewController()
let mutable initializedView = None
override this.ViewDidLoad() =
base.ViewDidLoad()
initializedView := Some(viewInitialized this.View)
override this.OtherMethod() =
viewInitialized |> Option.iter (fun vi ->
vi.OtherMethod() )
在它有视图时调用你的函数,然后你的函数创建一个处理另一个方法的新接口 - 但你的接口只在之后创建正确初始化!
MyViewController
但是我不太了解Xamarin是否可以在一个更复杂的系统中运行。
答案 1 :(得分:3)
我认为@Carsten得到的是你不应该引入空值,除非你绝对被迫与其他CLI语言互操作。在F#中声明的类型无论如何都不允许它们,除非用Option<'a>
装饰。
type MyViewController() =
inherit UIViewController()
let mutable animator = Option<UIDynamicAnimator>.None
member x.Animator = animator.Value
override this.ViewDidLoad() =
base.ViewDidLoad()
animator <- Some <| new UIDynamicAnimator(this.View)
类型中包含的值将是一种直接的翻译,但仍具有可变性。我假设您不需要属性设置器,将自动属性替换为let-bound值。
Lazy<'a>
另一方面,在type MyViewController() as this =
inherit UIViewController()
let animator = lazy(new UIDynamicAnimator(this.View))
member x.Animator = animator.Value
override this.ViewDidLoad() =
base.ViewDidLoad()
// Optional; only if you need the object creation right now
animator.Force() |> ignore
中包装更具功能性。
{{1}}