Main Content

핸들 클래스 소멸자

기본 정보

클래스 소멸자 – MATLAB®이 핸들 클래스의 객체를 소멸시키기 전에 묵시적으로 호출하는 delete라는 이름의 메서드입니다. 또한, 사용자 정의 코드는 delete를 명시적으로 호출하여 객체를 소멸시킬 수 있습니다.

비소멸자 – 유효한 소멸자에 대한 구문 요구 사항을 충족하지 않는 delete 메서드입니다. 따라서 MATLAB은 핸들 객체를 소멸시킬 때 이 메서드를 묵시적으로 호출하는 게 아니라 명시적으로 호출합니다. 값 클래스의 delete 메서드는 소멸자가 아닙니다. HandleCompatible 특성을 true로 설정하는 값 클래스에 있는 delete라는 이름의 메서드는 소멸자가 아닙니다.

객체 라이프사이클

메서드 특성

핸들 클래스 소멸자 메서드 구문

MATLAB은 클래스의 객체를 소멸시킬 때 핸들 클래스의 소멸자를 호출합니다. 사용자가 적합한 구문을 사용하여 delete를 일반 메서드로 정의하는 경우에만 delete 메서드가 MATLAB에서 클래스 소멸자로 인식됩니다.

유효한 클래스 소멸자가 되려면 delete 메서드가 다음 조건을 준수해야 합니다.

  • 클래스의 객체인 스칼라 입력 인수 하나를 정의해야 합니다.

  • 출력 인수를 정의하지 않아야 합니다.

  • Sealed, Static 또는 Abstract일 수 없습니다.

  • 입력 인수 유효성 검사에 arguments 블록을 사용할 수 없습니다.

또한, delete 메서드는 다음 조건을 준수해야 합니다.

  • 오류를 반환하지 않아야 합니다. 심지어 객체가 유효하지 않더라도 오류를 반환하지 않아야 합니다.

  • 소멸되는 객체에 대한 새 핸들을 생성하지 않아야 합니다.

  • 서브클래스의 속성에 액세스하거나 서브클래스의 메서드를 호출하지 않아야 합니다.

MATLAB은 클래스의 객체를 소멸시킬 때 이러한 조건을 준수하지 않는 delete 메서드를 호출하지 않습니다. 위의 조건을 준수하지 않는 delete 메서드는 handle 클래스의 delete 메서드를 가려서 객체가 소멸되지 않게 할 수 있습니다.

delete 메서드가 핸들 호환성이 있는 값 클래스로 정의되었다면 핸들 서브클래스에서 상속되었다 하더라도 이 delete 메서드는 소멸자가 아닙니다. 핸들 호환성을 지닌 클래스에 대한 자세한 내용은 Handle Compatible Classes 항목을 참조하십시오.

delete를 일반 메서드로 선언합니다.

methods
   function delete(obj)
      % obj is always scalar
   ...
   end
end

배열에 대해 요소별 delete 호출

MATLAB은 배열에 포함된 각 요소에 대해 개별적으로 delete 메서드를 호출합니다. 따라서, 각 호출마다 delete 메서드에 하나의 스칼라 인수만 전달됩니다.

삭제된 핸들에 대해 delete를 호출해도 오류가 발생하지 않고 아무런 동작도 수행되지 않습니다. 이러한 설계를 통해 delete는 유효한 객체와 유효하지 않은 객체가 혼합된 객체 배열에서 작동할 수 있습니다.

delete 메서드 실행 중의 핸들 객체

객체에 대해 delete 메서드를 호출하면 항상 객체가 소멸됩니다. delete가 MATLAB 코드에서 명시적으로 호출되거나 어떠한 작업 공간에서도 더 이상 이 객체에 접근할 수 없어 MATLAB에 의해 묵시적으로 호출된 경우, 객체가 소멸하게 됩니다. delete 메서드는 일단 호출되고 나면 객체 소멸을 중단하거나 방지할 수 없습니다.

delete 메서드는 삭제되는 객체의 속성에 액세스할 수 있습니다. MATLAB은 객체의 클래스 및 모든 슈퍼클래스에 대한 delete 메서드가 실행을 마칠 때까지 이러한 속성을 소멸시키지 않습니다.

delete 메서드가 삭제되는 객체에 대한 핸들을 포함하는 새 변수를 생성하는 경우 이러한 핸들은 유효하지 않습니다. delete 메서드가 실행을 마친 후에는 어떠한 작업 공간의 어떠한 변수에서든 그 안에 들어 있는 삭제된 객체에 대한 핸들은 더 이상 유효하지 않게 됩니다.

delete 메서드가 호출될 때 객체 소멸이 시작되기 때문에 이 메서드 내에 있는 핸들 객체에 대해 isvalid 메서드는 false를 반환합니다.

MATLAB은 생성 순서와 반대로 delete 메서드를 호출합니다. 즉, MATLAB은 서브클래스의 delete 메서드를 호출한 후 슈퍼클래스의 delete 메서드를 호출합니다.

슈퍼클래스의 속성이 서브클래스에 의해 관리되어야 하는 경우 슈퍼클래스는 자신의 delete 메서드에서 이 속성에 액세스하지 않아야 합니다. 예를 들어, 서브클래스가 상속된 추상 속성을 사용하여 객체 핸들을 저장하는 경우 서브클래스가 자신의 delete 메서드에서 이 객체를 소멸시켜야 하며, 슈퍼클래스는 자신의 delete 메서드에서 이 속성에 액세스하지 않아야 합니다.

부분적으로 생성된 객체에 대한 소멸 지원

객체를 생성하는 중에 오류가 발생하면 객체가 완전히 생성되기 전에 delete가 호출될 수 있습니다. 따라서, 클래스의 delete 메서드가 부분적으로 생성된 객체를 다룰 수 있어야 합니다.

예를 들어, PartialObject 클래스의 delete 메서드는 Data 속성에 들어 있는 데이터에 액세스하기 전에 속성이 비어 있는지 여부를 확인합니다. 생성자 인수를 Name 속성에 할당하는 동안 오류가 발생하면 MATLAB이 부분적으로 생성된 객체를 delete에 전달합니다.

classdef PartialObject < handle
   properties
      % Restrict the Name property
      % to a cell array
      Name cell
      Data
   end
   methods
      function h = PartialObject(name)
         if nargin > 0
            h.Name = name;
            h.Data.a = rand(10,1);
         end
      end
      function delete(h)
         % Protect against accessing properties
         % of partially constructed objects
         if ~isempty(h.Data)
            t = h.Data.a;
            disp(t)
         else
            disp('Data is empty')
         end
      end
   end
end

필요한 셀형 배열 대신 char형 벡터를 사용하여 생성자를 호출하면 오류가 발생합니다.

obj = PartialObject('Test')

MATLAB은 부분적으로 생성된 객체를 delete 메서드에 전달합니다. Name 속성을 설정할 때 오류가 발생하므로 생성자가 Data 속성의 값을 설정하지 않습니다.

Data is empty
Error setting 'Name' property of 'PartialObject' class:
...

소멸자 메서드를 정의해야 하는 경우

MATLAB이 객체를 소멸시키기 전에 delete 메서드를 사용하여 정리 작업을 수행하십시오. Ctrl+C를 누르거나 오류로 인해 실행이 중단되는 경우에도 MATLAB이 delete 메서드를 안정적으로 호출합니다.

핸들 클래스를 생성하는 도중 오류가 발생하면 MATLAB은 속성에 포함된 객체의 소멸자 및 초기화된 기본 클래스의 소멸자와 함께 객체에 대한 클래스 소멸자를 호출합니다.

예를 들어, 메서드가 쓰기 목적으로 파일을 여는데 사용자가 delete 메서드로 파일을 닫으려 한다고 가정하겠습니다. delete 메서드는 객체가 FileID 속성에 저장하는 파일 식별자에 대해 fclose를 호출할 수 있습니다.

function delete(obj)
   fclose(obj.FileID);
end 

클래스 계층 구조 내 소멸자

클래스의 계층 구조를 생성하는 경우 각 클래스가 자체 delete 메서드를 정의할 수 있습니다. 객체를 소멸시키는 동안 MATLAB이 계층 구조 내 각 클래스에 대한 delete 메서드를 호출합니다. handle 서브클래스에서 delete 메서드를 정의해도 handle 클래스의 delete 메서드는 재정의되지 않습니다. 서브클래스의 delete 메서드는 슈퍼클래스의 delete 메서드를 확장합니다.

봉인(Sealed) delete 메서드 상속하기

클래스는 Sealed인 유효한 소멸자를 정의할 수 없습니다. Sealed delete 메서드를 정의하는 클래스를 인스턴스화하려고 하면 MATLAB이 오류를 반환합니다.

일반적으로, 메서드를 Sealed로 선언하면 서브클래스가 해당 메서드를 재정의할 수 없게 됩니다. 하지만 유효한 소멸자가 아니면서 이름이 deleteSealed 메서드는 서브클래스가 자체 소멸자를 정의하지 못하도록 차단하지 않습니다.

예를 들어, 슈퍼클래스에서 유효한 소멸자가 아니면서 Sealeddelete 메서드를 정의하는 경우 서브클래스는 다음과 같은 상태가 됩니다.

  • 유효한 소멸자를 정의할 수 있습니다(이름이 항상 delete임).

  • 유효한 소멸자가 아닌 delete 메서드는 정의할 수 없습니다.

이종 계층 구조 내 소멸자

이종 클래스 계층 구조에서는 이종 배열을 전달 받는 모든 메서드가 봉인되어야 합니다. 하지만 클래스 소멸자 메서드에는 이 규칙이 적용되지 않습니다. 소멸자 메서드는 봉인될 수 없으므로, 이종 계층 구조에서는 소멸자로 작동하는 봉인되지 않은 유효한 생성자를 정의할 수 있습니다.

이종 계층 구조에 대한 자세한 내용은 Designing Heterogeneous Class Hierarchies 항목을 참조하십시오.

객체 라이프사이클

객체의 라이프사이클이 종료되면 MATLAB이 delete 메서드를 호출합니다. 객체가 다음과 같은 경우 객체의 라이프사이클이 종료됩니다.

  • 어느 위치에서도 더 이상 참조되지 않는 경우

  • 핸들에 대해 delete를 호출하여 명시적으로 삭제되는 경우

함수 내부

지역 변수 또는 입력 인수가 참조하는 객체의 라이프사이클은 변수가 할당된 시점부터 그 변수가 해당 함수 또는 핸들 배열 내에서 다시 할당되거나 지워지거나 더 이상 참조되지 않을 때까지입니다.

변수를 명시적으로 지우거나 해당 함수가 종료되면 변수가 범위를 벗어나게 됩니다. 변수가 범위를 벗어나고 변수 값이 delete 메서드를 정의하는 핸들 클래스에 속하는 경우 MATLAB이 그 메서드를 호출합니다. MATLAB은 함수에 포함된 변수 간에 순서를 정의하지 않습니다. 동일한 함수에 여러 값이 포함된 경우 MATLAB이 어떤 값을 다른 값보다 먼저 소멸시킨다고 가정하지 마십시오.

핸들 객체 소멸 순서

MATLAB은 객체를 소멸시키는 과정에서 다음과 같은 순서로 delete 메서드를 호출합니다.

  1. 객체의 클래스에 대한 delete 메서드

  2. 각 슈퍼클래스의 delete 메서드. 직속 슈퍼클래스부터 시작하여 계층 구조의 상위로 가장 일반적인 슈퍼클래스까지 진행

MATLAB은 클래스 정의에 지정된 순서에 따라 계층 구조에서 동일한 수준에 있는 슈퍼클래스의 delete 메서드를 호출합니다. 예를 들어, 다음 클래스 정의는 supclass2 앞에 supclass1을 지정합니다. MATLAB은 supclass2delete 메서드를 호출하기 전에 supclass1delete 메서드를 호출합니다.

classdef myClass < supclass1 & supclass2

delete 메서드를 호출할 때마다 MATLAB은 메서드가 호출된 클래스에만 속하는 속성값을 소멸시킵니다. 그러나 속성값에 클래스의 범위 밖에서 여전히 참조되는 핸들 객체가 포함된 경우, 이를 포함하는 객체에 대해 delete를 호출해도 속성 핸들 객체 자체는 삭제되지 않습니다. 다른 기존 참조를 사용하여 계속 액세스할 수 있습니다.

슈퍼클래스의 delete 메서드는 서브클래스에 속하는 메서드를 호출하거나 서브클래스에 속하는 속성에 액세스할 수 없습니다.

순환 참조가 있는 객체의 소멸

다른 객체를 참조하는 객체들로 구성된 집합이 있고, 이때의 참조가 순환 그래프를 이룬다고 가정해 보겠습니다. 이 경우, MATLAB은 다음과 같이 동작합니다.

  • 객체가 순환 내에서만 참조되는 경우 객체를 소멸시킵니다.

  • 순환 외부의 MATLAB 변수에서 객체에 대한 외부 참조가 있는 경우 객체를 소멸시키지 않습니다.

MATLAB은 생성된 순서와 반대로 객체를 소멸시킵니다. 자세한 내용은 delete 메서드 실행 중의 핸들 객체 항목을 참조하십시오.

객체의 delete 메서드에 대한 액세스 제한하기

객체에 대해 delete를 명시적으로 호출하여 핸들 객체를 소멸시킬 수 있습니다.

delete(obj)

클래스는 delete 메서드의 Access 특성을 private으로 설정하여 객체에 대한 명시적인 소멸을 방지할 수 있습니다. 하지만 클래스의 메서드는 private delete 메서드를 호출할 수 있습니다.

클래스의 delete 메서드에 대한 Access 특성이 protected이면 클래스와 서브클래스의 메서드만 클래스의 객체를 명시적으로 소멸시킬 수 있습니다.

그러나 객체 라이프사이클이 종료되면, MATLAB은 객체를 소멸시킬 때 메서드의 Access 특성에 관계없이 객체의 delete 메서드를 호출합니다.

상속된 프라이빗 delete 메서드

클래스 소멸자 동작은 재정의된 메서드의 일반 동작과 다릅니다. MATLAB은 해당 delete 메서드가 public이 아니더라도 소멸 시에 각 슈퍼클래스의 delete 메서드를 개별적으로 실행합니다.

객체의 delete 메서드를 명시적으로 호출하면 MATLAB은 객체의 슈퍼클래스가 아니라 객체를 정의하는 클래스에서 delete 메서드의 Access 특성을 확인합니다. private delete 메서드를 갖는 슈퍼클래스는 서브클래스 객체의 소멸을 방지할 수 없습니다.

봉인 클래스의 경우에는 프라이빗 delete 메서드를 선언하는 것이 가장 적합합니다. 클래스가 봉인되지 않은 경우 서브클래스는 퍼블릭 액세스를 갖는 자체 delete 메서드를 정의할 수 있습니다. MATLAB은 퍼블릭 서브클래스 delete 메서드를 명시적으로 호출한 결과로 프라이빗 슈퍼클래스의 delete 메서드를 호출합니다.

비소멸자 delete 메서드

클래스는 유효한 클래스 소멸자가 아닌 delete 메서드를 구현할 수 있습니다. MATLAB은 객체를 소멸시킬 때 이 메서드를 묵시적으로 호출하지 않습니다. 이 경우, delete는 일반 메서드처럼 동작합니다.

예를 들어, 슈퍼클래스에서 유효한 소멸자가 아니면서 이름이 deleteSealed 메서드를 구현하면 MATLAB은 서브클래스가 이 메서드를 재정의하는 것을 허용하지 않습니다.

값 클래스에서 정의한 delete 메서드는 클래스 소멸자가 될 수 없습니다.

MATLAB 객체에 대한 외부 참조

MATLAB은 자체적인 객체 라이프사이클 관리(가비지 컬렉션이라고도 함)를 수행하는 외부 언어가 수반된 객체의 라이프사이클은 관리하지 않습니다. 외부 참조가 소멸되었을 때 외부 환경으로부터 MATLAB에 통지되지 않기 때문에 MATLAB은 순환 참조에 사용된 객체를 소멸시키기에 안전한 시기를 감지할 수 없습니다.

MATLAB 객체에 대한 외부 참조를 피할 수 없는 경우 MATLAB의 객체를 소멸시켜 순환 참조를 명시적으로 끊으십시오.

다음 섹션에서는 MATLAB 객체를 참조하는 Java® 객체를 사용할 때 이러한 상황을 관리하는 방법을 설명합니다.

Java 참조를 통해 소멸자 실행 방지 가능

Java는 MATLAB 객체가 사용하는 객체 소멸자를 지원하지 않습니다. 따라서, Java 객체와 MATLAB 객체가 둘 다 포함된 애플리케이션에서는 모든 객체의 라이프사이클을 관리하는 일이 상당히 중요합니다.

MATLAB 객체에 대한 참조를 유지하는 Java 객체는 MATLAB 객체가 삭제되는 것을 방해할 수 있습니다. 이 경우, MATLAB은 해당 객체를 참조하는 핸들 변수가 없더라도 핸들 객체의 delete 메서드를 호출하지 않습니다. delete 메서드가 실행되도록 하려면 핸들 변수가 범위를 벗어나기 전에 객체에 대해 delete를 명시적으로 호출하십시오.

MATLAB 객체를 참조하는 Java 객체에 대한 콜백을 정의할 때 문제가 발생할 수 있습니다.

CallbackWithJava 클래스가 Java com.mathworks.jmi.Callback 객체를 생성하고 클래스 메서드를 콜백 함수로 할당하는 경우를 예로 살펴보겠습니다. 그 결과, 함수 핸들 콜백을 통해 핸들 객체에 대한 참조를 갖는 Java 객체가 생성됩니다.

classdef CallbackWithJava < handle
   methods
      function obj = CallbackWithJava
         jo = com.mathworks.jmi.Callback;
         set(jo,'DelayedCallback',@obj.cbFunc); % Assign method as callback
         jo.postCallback
      end
      function cbFunc(obj,varargin)
         c = class(obj);
         disp(['Java object callback on class ',c])
      end
      function delete(obj)
         c = class(obj);
         disp(['ML object destructor called for class ',c])
      end
   end
end

함수 내에서 CallbackWithJava 객체를 생성한다고 가정하겠습니다.

function testDestructor
   cwj = CallbackWithJava
   ...
end

CallbackWithJava 클래스의 인스턴스를 생성하면 com.mathworks.jmi.Callback 객체가 생성되고 콜백 함수가 실행됩니다.

testDestructor
cwj = 

  CallbackWithJava with no properties.

Java object callback on class CallbackWithJava

핸들 변수 cwj는 함수 작업 공간에만 존재합니다. 하지만 MATLAB은 함수가 종료될 때 클래스의 delete 메서드를 호출하지 않습니다. com.mathworks.jmi.Callback 객체가 여전히 존재하고 CallbackWithJava 클래스의 객체에 대한 참조를 유지하므로 이로 인해 MATLAB 객체는 삭제되지 않습니다.

clear classes
Warning: Objects of 'CallbackWithJava' class exist.  Cannot clear this class or
any of its superclasses. 

액세스할 수 없는 객체가 생기지 않게 하려면 MATLAB 객체에 대한 핸들을 잃기 전에 delete를 명시적으로 호출하십시오.

function testDestructor
   cwj = CallbackWithJava
   ...
   delete(cwj)
end

애플리케이션에서 객체 라이프사이클 관리하기

Java 또는 다른 외부 언어 객체를 사용하는 MATLAB 애플리케이션은 관련 객체의 라이프사이클을 관리해야 합니다. 일반적인 사용자 인터페이스 애플리케이션은 MATLAB 객체에서 Java 객체를 참조하고 MATLAB 객체를 참조하는 Java 객체에 대한 콜백을 생성합니다.

다음과 같은 다양한 방법으로 이러한 순환 참조를 끊을 수 있습니다.

  • MATLAB 객체가 더 이상 필요하지 않은 경우 이 객체에 대한 delete를 명시적으로 호출합니다.

  • MATLAB 객체를 참조하는 Java 객체 콜백의 등록을 해제합니다.

  • Java 콜백과 MATLAB 객체를 둘 다 참조하는 중간 핸들 객체를 사용합니다.

관련 항목