2

コンストラクターを呼び出すときに、同じクラスの前のオブジェクトをデフォルトのオブジェクトに置き換えるか、単に前のオブジェクトを使用するかをユーザーに尋ねる方法を見つけようとしています。

私はこれらの両方のケースでアクションを探しています:

>>obj = Obj()
'obj' already exists. Replace it with default? (y/n): y
%clear obj and call default constructor to create new obj

>>obj = Obj()
'obj' already exists. Replace it with default? (y/n): n
%cancel call of Obj()

どうすればいいですか?デフォルトのコンストラクターをいじりましたが、役に立ちませんでした。

編集:違いがある場合、Obj はハンドルのサブクラスです。

4

3 に答える 3

4

次の解決策は、いくつかの回避策/ハックから生じたものであり、標準の MATLAB の OO 構造の一部ではありません。注意して使用してください。

必要がある:

  1. evalin()ワークスペース変数'caller'の名前とクラスをワークスペースに'base'
  2. 最後に実行されたコマンドを取得する
  3. たとえば、割り当てられた変数の名前を抽出しますregexp()
  4. 名前とクラスを比較します。完全に一致した場合、つまり、'base'ワークスペース内の変数が同じクラスの新しいインスタンスで上書きされている場合は、ユーザーにinput(). ユーザーが既存のオブジェクトを保持することを選択した場合は、新しいインスタンスを既存のインスタンスで上書きしますevalin('caller',...)

クラスfoo:

classdef foo < handle
    properties
        check = true;
    end
    methods
        function obj = foo()
            % variable names and sizes from base workspace
            ws = evalin('base','whos');

            % Last executed command from window
            fid = fopen([prefdir,'\history.m'],'rt');
            while ~feof(fid)
                lastline = fgetl(fid);
            end
            fclose(fid);

            % Compare names and classes
            outname = regexp(lastline,'\<[a-zA-Z]\w*(?=.*?=)','match','once');
            if isempty(outname);  outname = 'ans'; end

            % Check if variables in the workspace have same name
            idx = strcmp({ws.name}, outname);
            % Ask questions
            if any(idx) && strcmp(ws(idx).class, 'foo')
                s = input(sprintf(['''%s'' already exists. '...
                     'Replace it with default? (y/n): '],outname),'s');
                % Overwrite new instance with existing one to preserve it
                if strcmpi(s,'n')
                    obj = evalin('caller',outname);
                end
            end
        end
    end
end

活動中のクラス:

% create class and change a property from default (true) to false
clear b

b = foo
b = 
  foo with properties:
    check: 1

b.check = false
b = 
  foo with properties:
    check: 0

% Avoid overwriting
b = foo
'b' already exists. Replace it with default? (y/n): n

b
b = 
  foo with properties:
    check: 0

弱点(上記のポイントを参照):

  1. cmw 行とスクリプトで実行されるコマンドにのみ適用され、関数には適用されません (関数呼び出しに拡張するためのリンクを参照してください)。また、 history.mの読み取りで問題が発生した場合に壊れる可能性があります。
  2. 現在の正規表現は で失敗しa==bます。
  3. ユーザー入力evalin()が潜在的なセキュリティ上の脅威にさらされるため、危険です。入力が正規表現と文字列比較でフィルター処理されたとしても、コードが後で再検討されると、構造が問題を引き起こす可能性があります。
于 2013-07-11T18:52:14.240 に答える
2

シングルトン

これを試してみてください。慣れているかどうかはわかりませんが、これは、この特定のオブジェクトのグローバル インスタンスが 1 つしかないことを意味します。

于 2013-07-11T17:26:18.243 に答える
0

関数 (こちらのドキュメントisobject()を参照) を使用して、変数がオブジェクトかどうかを確認できます。true の場合、オブジェクトのクラスをチェックして(こちらのドキュメントを参照)、作成するオブジェクトのクラスと比較できます。次のようなもの(アイデアを提供するため):class()

if isobject(obj)
    if class(obj) == myclass
        % ask to replace it or not
    else
        % create new one over the object of a different class
    end
else
    % create new one
end

私があなたの質問を正しく理解していれば、おそらくこれをクラスのコンストラクター関数として配置したいと思うでしょう。コンストラクターを呼び出すときに変数名を渡す必要があると思います: obj = Obj(obj)

于 2013-07-09T17:22:22.953 に答える