0

在matlab中,我有一个类在构造过程中绑定共享资源并在删除时释放它。(在我的具体情况下,共享资源是一个我可以通过 http://localhost:1234 与之交互的端口)

它看起来像这样:

classdef myClass < handle
    methods
        function myClass()
            OpenExecutableUsingPort1234();
        end
        function delete(this)
            CloseExecutableUsingPort1234();
        end
    end
end

当我这样使用它时:

instance = myClass();
clear instance;

一切正常。我打开和关闭它没有问题。但是当我这样使用它时:

instance = myClass();
instance = myClass(); % can't access the port during construction, because it's in use.

我无法启动可执行文件,因为该端口正在使用中。

事件顺序是这样的:

  1. 构造了 myClass 的第一个副本。端口没有问题
  2. 副本被分配给“实例”变量。
  3. 构造了 myClass 的第二个副本。它无法启动可执行文件,因为端口正在使用中
  4. 新副本分配给“实例”变量
  5. 第一个副本不再有任何引用,并调用其删除方法。这释放了端口。

什么样的解决方法是可能的?

理想情况下,我希望第 5 步只知道它需要提前运行:

  1. 构造了 myClass 的第一个副本。端口没有问题
  2. 副本被分配给“实例”变量。

5. 第一个副本不再有任何对它的引用,并调用它的删除方法。这释放了端口。

  1. 构造了 myClass 的第二个副本。港口也是免费的!
  2. 新副本分配给“实例”变量
4

1 回答 1

1

如果您希望旧实例在新实例开始创建之前消失,您必须手动清除。

如果你这样做:

instance = myClass();
instance = myClass();

第二行在变量被重新分配myClass之前调用构造函数instance,在第一个实例上触发 GC。在第二个构造函数返回之前它不会改变instance,并且它有一个新值可以放入其中。(例如,如果 myClass 构造函数抛出错误,instance则应保持不变。)

只需在其中明确说明:

instance = myClass;
clear instance
instance = myClass;

(据我所知,Matlab 语言规范不能保证这种行为,但这是目前的工作方式。)

例子:

classdef Deletable < handle
    
    properties
        id
    end
    
    methods
        
        function this = Deletable
            persistent nextId
            if isempty(nextId)
                nextId = 1;
            end
            this.id = nextId;
            nextId = nextId + 1;
            fprintf('Hello! id=%d\n', this.id);
        end
        
        function delete(this)
            fprintf('Bye bye! id=%d\n', this.id);
        end
        
    end
    
end

function without_clear

instance = Deletable;
instance = Deletable;

end


function with_clear

instance = Deletable;
clear instance
instance = Deletable;

end

行为:

>> without_clear
Hello! id=5
Hello! id=6
Bye bye! id=5
Bye bye! id=6
>> 
>> with_clear
Hello! id=7
Bye bye! id=7
Hello! id=8
Bye bye! id=8
>> 

如果您真的希望它以不同的方式工作,您可以编写您的类,以便只有一个活动实例。persistent在类定义的变量中保留它。当创建一个新实例时,让它吹走前一个实例中的实际连接。不过我觉得这有点恶心。

或者只使用类的单个 Singleton 实例,并使其属性可变,以便您可以更改其状态而不是创建新实例。

于 2021-09-18T15:14:37.213 回答