问题描述
我正在尝试从序列中对特定类型的对象调用函数,但是编译器会抱怨。
该如何解决?我需要从text
个对象中获得TextDoc
属性。
type
DocItem = object of RootObj
tags: seq[string]
TextDoc = object of DocItem
text: string
TodoDoc = object of DocItem
todo: string
var docs: seq[ref DocItem]
proc to_ref[T](o: T): ref T =
result.new
result[] = o
docs.add TextDoc(text: "some doc").to_ref
docs.add TodoDoc(todo: "some todo").to_ref
for d in docs:
if d of TextDoc:
echo d.text
Error: undeclared field: 'text'
解决方法
要对已接受的答案发表评论,cast
是不安全的操作,除非有特殊原因,否则应避免使用它。您可以改用类型转换,如下所示:
for d in docs:
if d of ref TextDoc:
echo TextDoc(d[]).text
如果您制作了TextDoc
和TodoDoc
ref object of DocItem
,则可以摆脱to_ref
的proc并编写如下的循环:
for d in docs:
if d of TextDoc:
echo TextDoc(d).text
或者您可以使用对象变量,这可能是最惯用的方法:
type
DocType = enum dtText,dtTodo
DocItem = ref object
tags: seq[string]
case kind: DocType
of dtText: text: string
of dtTodo: todo: string
var docs = @[DocItem(kind: dtText,text: "some doc"),DocItem(kind: dtTodo,todo: "some todo")]
for d in docs:
if d.kind == dtText:
echo d.text
,
of
条件不会神奇地转换其余块的类型,我会强制转换类型,或编写一个额外的帮助程序来实现:
proc toTextDoc(thing: ref DocItem): ref TextDoc = cast[ref TextDoc](thing)
proc toTodoDoc(thing: ref DocItem): ref TodoDoc = cast[ref TodoDoc](thing)
for d in docs:
if d of TextDoc:
echo d.toTextDoc.text
elif d of TodoDoc:
echo d.toTodoDoc.todo
else:
echo "Not a ref?"