gpt4 book ai didi

class - 使用其他方法创建 Ocaml 子类的正确方法是什么?

转载 作者:行者123 更新时间:2023-12-04 05:26:51 25 4
gpt4 key购买 nike

在 Ocaml 中,我正在努力处理子类化和类型:

class super =  
object (self)
method doIt =
...
end;

class sub =
object (self)
inherit super
method doIt =
...
self#somethingElse
...

method somethingElse =
...
end;

let myFunction (s:super) =
...

myFunction new sub

显然在 Ocaml 中,类 sub不是 super 的“子类型” ,因为 sub#doIt方法调用 sub 中的方法不存在于 super .然而,这似乎是面向对象编程的一个非常常见的用例。完成此操作的推荐方法是什么?

最佳答案

正如 Rémi 所提到的,您的代码的问题在于 OCaml 类型系统每个表达式仅支持一种类型:类型为 sub 的表达式。不是类型 super .在您的示例中,myFunction期望类型为 super 的参数,以及表达式 new sub类型为 sub ,因此问题。

Upcasting 对于面向对象编程是必不可少的,OCaml 确实通过两种不同的结构来支持它。

第一个是类型强制 .如 supersub 的父类(super class)型(意味着语义上,类型 sub 的值表现为 super 的值),和 x : sub ,然后 (x :> super) : super . :>类型运算符使转换显式 - 当您使用类型为 sub 的值时,流行的面向对象语言隐式执行的操作等效于哪里super是期待。

第二个是父类(super class)型约束 : 要求给定类型变量是给定类型的子类型。这写成 #super(#super as 'a)如果您希望在其中命名类型变量。父类(super class)型约束实际上并不像类型强制那样改变表达式的类型,它们只是检查类型是否是所需类型的有效子类型。

要更加了解差异,请考虑以下示例:

class with_size ~size = object 
val size = size : int
method size = size
end

class person ~name ~size = object
inherit with_size ~size
val name = name : string
method name = name
end

let pick_smallest_coerce (a : with_size) (b : with_size) =
if a # size < b # size then a else b

let pick_smallest_subtype (a : #with_size) (b : #with_size) =
if a # size < b # size then a else b
pic_smallest_coerce的类型是 with_size -> with_size -> with_size : 即使你通过了两个 person实例,返回值的类型为 with_size并且您将无法调用其 name方法。
pic_smallest_subtype的类型是 (#with_size as 'a) -> 'a -> 'a : 如果你通过了两个 person例如,类型系统将确定 'a = person并将返回值正确识别为类型 person (它允许您使用 name 方法)。

简而言之,父类(super class)型约束只是确保您的代码能够运行,根本不会丢失任何类型信息——变量保留其原始类型。类型强制实际上会丢失类型信息(在没有向下转换的情况下,这是一件非常讨厌的事情),因此它只能在两种情况下作为最后的手段使用:

1. 你不能有一个多态函数。父类(super class)型约束依赖于 #super作为一个自由类型变量,所以如果你不能在你的代码中拥有一个自由类型变量,你将不得不放弃它。

2. 您需要在同一个容器中实际存储不同实际类型的值。可以包含 person 的列表或引用或 box实例将使用 with_size和胁迫:
let things = [ my_person :> with_size ; my_box :> with_size ]

请注意,类型推断算法将自行发现父类(super class)型约束(它不会确定您打算使用什么类或类类型,但它会构造一个文字类类型):
let pick_smallest_infer a b = 
if a # size < b # size then a else b

val pick_smallest_infer : (< size : 'a ; .. > as 'b) -> 'b -> 'b

因此,除了极少数异常(exception),注释实际的父类(super class)型约束仅在记录代码时才是有用的练习。

关于class - 使用其他方法创建 Ocaml 子类的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4914791/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com