3

次のスニペットがあります。ただし、2 番目の変数宣言はコンパイルされません。

type 
  Coin = ref object
  Pen  = ref object

let 
  yes : seq[ref object] = @[Coin(), Coin(), Coin()]  #Compiles
  no  : seq[ref object] = @[Coin(), Pen(), Coin()]   #Does not compile

Javaのリストのように、nimで一般的なseqを使用することは可能ですか?

4

1 に答える 1

5

Nim シーケンス汎用的ですが、同じ種類のオブジェクトをそれらに入れているわけではありません。Java では、すべての非プリミティブ型 (配列を含む)は Object スーパークラスから直接的または間接的に継承されるため、型を持つことでそのList<Object>中に何でも入れることができます。しかし、Nim では、すべてが同じルートを持つ必要はありません。あなたの場合、オブジェクトは同じように見えますが、異なるタイプとして扱われます。したがって、Java のようなクラス階層を作成する必要があります。

type
  BaseRef = ref object of TObject
  CoinRef = ref object of BaseRef
  PenRef = ref object of BaseRef

let
  test1: seq[BaseRef] = @[(BaseRef)CoinRef(), CoinRef(), CoinRef()]
  test2: seq[BaseRef] = @[(BaseRef)CoinRef(), PenRef(), CoinRef()]

@[]リストコンストラクターは、最初の要素を基本型に変換する正しい方向に突き進む必要があることに注意してください。そうしないと、不等式が得られます ( a は aと同じでseq[BaseRef]なくseq[CoinRef]、型推論の結果となります)。

何らかの理由で別のルートを保持する必要がある場合は、参照であるため、それらを直接キャストしても問題ないはずです。そのためにヘルパー プロシージャを作成できます。

type 
  AnyRef = ref object
  Coin = ref object
  Pen  = ref object

proc `^`(x: Coin): AnyRef = cast[AnyRef](x)
proc `^`(x: Pen): AnyRef = cast[AnyRef](x)

let 
  yes : seq[AnyRef] = @[^Coin(), ^Coin(), ^Coin()]
  no  : seq[AnyRef] = @[^Coin(), ^Pen(), ^Coin()]

または、継承バージョンのように、すべての要素に対して明示的な変換を必要とせず、最初の要素のみを必要とするコンバータ プロシージャを作成することもできます。

type 
  AnyRef = ref object
  Coin = ref object
  Pen  = ref object

converter toAnyRef(x: Coin): AnyRef = cast[AnyRef](x)
converter toAnyRef(x: Pen): AnyRef = cast[AnyRef](x)

let 
  yes : seq[AnyRef] = @[Coin().toAnyRef, Coin(), Coin()]
  no  : seq[AnyRef] = @[Coin().toAnyRef, Pen(), Coin()]
于 2015-04-22T20:42:07.827 に答える