3

Eiffel では、Void Safety は、初期化されていない (「null」) オブジェクトの逆参照を静的に防止する方法です。それが機能する方法は、最初にオブジェクトをdetachableとして宣言する必要があり、次に、オブジェクトを使用する前に、オブジェクトが実際にアタッチされている (つまり、何らかの値がある)かどうかを if ブロックで確認する必要があります。

これは私が今までそれを使用してきた方法です:

some_object: detachable TYPE

...

if attached some_object then
  some_object.method
end

完全に正常に動作します。アタッチされたチェックがないと、コンパイルは「Object_call のターゲットが void である可能性があります」というエラーで失敗します。しかし、 Void Safetyに関するドキュメントを実際に読んだ後、これが実際には次のようになっていることがわかりました。

some_object: detachable TYPE

...

if attached some_object as l_some_object then
  l_some_object.method
end

この形式では、と同じオブジェクトを指しているが非 void であることが静的に保証されている if ブロックにローカルl_some_objectな変数です。some_object

しかし、この as-clause が存在する理由がわかりません。上で指摘したように、どうやらオリジナルsome_objectはすでに if ブロック内で非 void であることが静的に保証されているようですが、別の変数を導入する意味は何ですか?

スコープ以外のsome_objectとの違いは何ですか?l_some_object

4

1 に答える 1

4

簡潔な答え

がローカル変数の場合some_object、オブジェクト test local を導入しても意味がありませんl_some_object

長い答え

オブジェクト テストの一般的な形式は次のとおりです。

attached {SOME_TYPE} expr as var

{SOME_TYPE}varオプションです。type ({SOME_TYPE}上記の例) が使用されていない場合、オブジェクト テストexprは が添付されているかどうかを確認し、添付されている場合はその値を に割り当てますvar

理論的には、次のようなものは void-safe であると期待できます。

if attached expr then
    expr.do_something
end

ただし、expr副作用がある可能性があるため、これは一般的なケースでは許可されていません。そのため、2 回目の計算では別の値が返され、この値voidによってコードが void-unsafe になる可能性があります。

if attached foo then -- On first call function foo returns non-void value.
    foo.do_something -- On second call function foo returns void: BOOM!
end

別の可能性は、式の値を変更する中間呼び出しです。たとえば、

if attached attr then -- Attribute attr is attached here.
    bar               -- bar sets attr to Void.
    attr.do_something -- BOOM!
end

bar属性attrを(これvoidは間接的に行うことができます) に設定すると、コードは再び void-unsafe になります。

attr最後に、マルチスレッド環境では、中間の機能呼び出しがなくても、チェックの後、「then」部分内で使用する前に、別のスレッドが の値を変更する可能性があります。

if attached attr then -- Attribute attr is attached here.
                      -- Another thread sets attr to Void.
    attr.do_something -- BOOM!
end

これらの状況を防ぐために、var部品が使用されます。このオブジェクト テスト ローカルは読み取り専用であり、同じ式の評価、中間機能呼び出し、または別のスレッドによる影響を受けません。つまり、常に接続されています。

オブジェクト テストの式がこれらの要因の影響を受けない場合もあります。

  1. 引数は読み取り専用なので、短い形式を使用するだけで常に十分です

    attached arg
    

    また、オブジェクト test local を導入しても意味がありません。なぜなら、それは常に引数と等しいからです。

  2. ローカル変数は、取り外し可能な式が割り当てられている場合にResultのみになる可能性があります。Voidそのような割り当てがない場合、同じ

    attached local_var
    

    大丈夫です。ただし、ローカルに取り外し可能な式が割り当てられるとすぐに、関連付けられているとは見なされなくなります。

    if attached local_var then
        ... -- OK to use local_var as attached.
        local_var := detachable_expression
        ... -- No guarantees about local_var attachment status.
    end
    

    このシナリオが望ましくない場合は、長い形式のオブジェクト テストを使用できます。

    attached local_var as attached_local_var
    

    attached_local_var常に接続されていることを保証します。

于 2016-05-06T21:39:17.803 に答える