클래스 멤버 액세스
기본 정보
이 섹션에 나와 있는 자료는 다음 개념에 대한 이해를 바탕으로 합니다.
액세스 제어 목록을 사용하는 응용 사례
액세스 제어 목록을 통해 특정 클래스 속성, 메서드, 이벤트에 대한 액세스를 제어할 수 있습니다. 액세스 제어 목록은 클래스 멤버 단위로 액세스를 부여할 클래스의 목록을 지정합니다.
이 기법은 클래스 시스템을 설계할 때 더욱 큰 유연성과 제어 기능을 제공합니다. 예를 들어, 액세스 제어 목록을 사용하여 개별 클래스를 정의하되, 클래스 시스템 외부에서는 클래스 멤버에 액세스할 수 없게 할 수 있습니다.
클래스 멤버에 대한 액세스 지정하기
멤버 액세스 특성 문에서 특정 클래스 멤버에 액세스하도록 허용하는 클래스를 지정할 수 있습니다. 예를 들면 다음과 같습니다.
methods (Access = {?ClassName1,?ClassName2,...})
클래스의 meta.class
객체를 사용하여 액세스 목록의 클래스를 참조합니다. 둘 이상의 클래스를 지정하려면 meta.class
객체로 구성된 셀형 배열을 사용하십시오. 패키지에 포함된 클래스를 참조할 때에는 패키지 이름을 사용해야 합니다.
참고
meta.class
객체(?
연산자로 생성)를 명시적으로 지정하되, 함수 또는 다른 MATLAB 표현식에서 반환된 값으로는 지정하지 마십시오.
MATLAB이 특성 값을 해석하는 방법
클래스 목록에 액세스를 부여하면 액세스가 다음으로만 제한됩니다.
정의 클래스
목록에 포함된 클래스
목록에 포함된 클래스의 서브클래스
액세스 목록에 정의 클래스를 포함시키면 정의 클래스의 모든 서브클래스에 대한 액세스도 부여됩니다.
MATLAB은 클래스를 불러올 때에만 액세스 목록에 포함된 클래스에 대한 참조를 확인합니다. MATLAB이 액세스 목록에 포함된 클래스를 찾을 수 없는 경우 해당 클래스는 실질적으로 액세스에서 제거됩니다.
MATLAB은 목록에 있지만 확인되지 않은
meta.class
항목을 빈meta.class
객체로 바꿉니다.빈 액세스 목록(즉, 빈 셀형 배열)은
private
액세스와 동일합니다.
메타클래스 객체 지정하기
?
연산자와 클래스 이름만 사용하여 meta.class
객체를 생성합니다. 특성에 할당되는 값은 허용된 다음과 같은 특성 값을 반환하는 함수를 비롯하여 다른 MATLAB 표현식을 포함할 수 없습니다.
meta.class
객체meta.class
객체로 구성된 셀형 배열값
public
,protected
또는private
이러한 값은 이 섹션의 예제 코드에 표시된 것처럼 명시적으로 지정해야 합니다.
액세스 목록을 갖는 속성
다음 예제 클래스에서는 읽기 액세스(GetAccess
)를 클래스에 부여하는 속성의 동작을 보여줍니다. GrantAccess
클래스는 GetAccess
를 Prop1
속성의 NeedAccess
클래스에 부여합니다.
classdef GrantAccess properties (GetAccess = ?NeedAccess) Prop1 = 7 end end
NeedAccess
클래스는 GrantAccess
Prop1
값을 사용하는 메서드를 정의합니다. dispObj
메서드는 Static
메서드로 정의되지만, 일반 메서드일 수 있습니다.
classdef NeedAccess methods (Static) function dispObj(GrantAccessObj) disp(['Prop1 is: ',num2str(GrantAccessObj.Prop1)]) end end end
Prop1
에 대한 Get 액세스는 프라이빗이므로 클래스 정의 외부에서 속성에 액세스하려고 하면 MATLAB이 오류를 반환합니다. 명령줄에서 다음을 실행하는 경우를 예로 들 수 있습니다.
a = GrantAccess; a.Prop1
Getting the 'Prop1' property of the 'GrantAccess' class is not allowed.
하지만 MATLAB에서는 NeedAccess
클래스를 통해 Prop1
에 액세스할 수 있도록 허용합니다.
NeedAccess.dispObj(a)
Prop1 is: 7
액세스 목록을 갖는 메서드
메서드에 대한 액세스가 부여된 클래스는 다음을 수행할 수 있습니다.
정의 클래스의 인스턴스를 사용하여 메서드를 호출할 수 있습니다.
동일한 이름으로 자체 메서드를 정의할 수 있습니다(서브클래스가 아닌 경우에 한함).
메서드를 정의하는 슈퍼클래스가 액세스 목록에 자기 자신 또는 서브클래스를 포함하는 경우에만 서브클래스의 메서드를 오버라이드할 수 있습니다.
다음 예제 클래스에서는 액세스 목록에 포함된 다른 클래스의 메서드에서 호출된 메서드의 동작을 보여줍니다. AcListSuper
클래스는 AcListNonSub
클래스에 m1
메서드에 대한 액세스를 부여합니다.
classdef AcListSuper methods (Access = {?AcListNonSub}) function obj = m1(obj) disp ('Method m1 called') end end end
AcListNonSub
가 m1
의 액세스 목록에 포함되어 있으므로 해당 메서드가 AcListSuper
의 인스턴스를 사용하여 m1
을 호출할 수 있습니다.
classdef AcListNonSub methods function obj = nonSub1(obj,AcListSuper_Obj) % Call m1 on AcListSuper class AcListSuper_Obj.m1; end function obj = m1(obj) % Define a method named m1 disp(['Method m1 defined by ',class(obj)]) end end end
두 클래스 모두에 대한 객체를 생성합니다.
a = AcListSuper; b = AcListNonSub;
AcListNonSub
메서드를 사용하여 AcListSuper
의 m1
메서드를 호출합니다.
b.nonSub1(a);
Method m1 called
AcListNonSub
의 m1
메서드를 호출합니다.
b.m1;
Method m1 defined by AcListNonSub
액세스가 부여되지 않은 서브클래스
메서드에 대한 액세스 목록에 정의 클래스를 포함시키면 정의 클래스에서 파생된 모든 서브클래스에도 액세스할 수 있습니다. 메서드에 액세스 목록이 지정되어 있는 클래스에서 서브클래스를 파생하는데 정의 클래스가 액세스 목록에 포함되어 있지 않다면 다음과 같은 특성을 갖게 됩니다.
서브클래스 메서드가 슈퍼클래스 메서드를 호출할 수 없습니다.
서브클래스 메서드가 액세스 목록에 포함된 클래스의 인스턴스를 사용하여 간접적으로 슈퍼클래스 메서드를 호출할 수 있습니다.
서브클래스가 슈퍼클래스 메서드를 오버라이드할 수 없습니다.
슈퍼클래스 메서드 액세스 목록에 포함되어 있지만 서브클래스 메서드가 아니라면 슈퍼클래스 메서드를 호출할 수 있습니다.
예를 들어, AcListSub
가 AcListSuper
의 서브클래스라고 가정하겠습니다. AcListSuper
클래스가 메서드 m1
에 대한 액세스 목록을 정의합니다. 하지만 이 목록에 AcListSuper
가 포함되어 있지 않아 AcListSuper
의 서브클래스가 메서드 m1
에 액세스할 수 없는 상황입니다.
classdef AcListSub < AcListSuper methods function obj = sub1(obj,AcListSuper_Obj) % Access m1 via superclass object (***NOT ALLOWED***) AcListSuper_Obj.m1; end function obj = sub2(obj,AcListNonSub_Obj,AcListSuper_obj) % Access m1 via object that is in access list (is allowed) AcListNonSub_Obj.nonSub1(AcListSuper_Obj); end end end
슈퍼클래스 메서드를 직접적으로 호출할 수 없음
sub1
메서드에서 슈퍼클래스의 m1
메서드를 호출하려고 하면 서브클래스가 m1
에 대한 액세스 목록에 없으므로 오류가 발생합니다.
a = AcListSuper; c = AcListSub; c.sub1(a);
Cannot access method 'm1' in class 'AcListSuper'. Error in AcListSub/sub1 (line 4) AcListSuper_Obj.m1;
슈퍼클래스 메서드를 간접적으로 호출할 수 있음
슈퍼클래스 메서드 액세스 목록에 포함된 클래스의 객체를 사용하여 해당 메서드에 대한 액세스를 가지지 않는 서브클래스에서 슈퍼클래스 메서드를 호출할 수 있습니다.
AcListSub
의 sub2
메서드는 m1
의 액세스 목록에 포함된 클래스(AcListNonSub
)의 메서드를 호출합니다. 메서드 nonSub1
은 슈퍼클래스의 m1
메서드에 액세스할 수 있습니다.
a = AcListSuper; b = AcListNonSub; c = AcListSub; c.sub2(b,a);
Method m1 called
슈퍼클래스 메서드를 재정의할 수 없음
슈퍼클래스가 메서드에 대한 액세스 목록에 포함되어 있지 않은 경우 이러한 서브클래스는 이름이 동일한 메서드를 정의할 수 없습니다. 이 동작은 메서드 Access
가 private
으로 명시적으로 선언된 경우와 동일하지 않습니다.
예를 들어, 다음 메서드를 AcListSub
클래스 정의에 추가하면 클래스를 인스턴스화하려고 할 때 오류가 발생합니다.
methods (Access = {?AcListNonSub}) function obj = m1(obj) disp('AcListSub m1 method') end end
c = AcListSub;
Class 'AcListSub' is not allowed to override the method 'm1' because neither it nor its superclasses have been granted access to the method by class 'AcListSuper'.
서브클래스를 통해 목록에 포함된 클래스에서 슈퍼클래스 호출하기
AcListNonSub
클래스는 m1
메서드 액세스 목록에 포함되어 있습니다. 이 클래스는 AcListSub
클래스의 객체를 사용하여 m1
메서드를 호출하는 메서드를 정의할 수 있습니다. AcListSub
는 메서드 m1
에 대한 액세스 목록에 포함되어 있지 않지만 AcListSuper
의 서브클래스입니다.
예를 들어, 다음 메서드를 AcListNonSub
클래스에 추가해 보겠습니다.
methods function obj = nonSub2(obj,AcListSub_Obj) disp('Call m1 via subclass object:') AcListSub_Obj.m1; end end
nonSub2
메서드를 호출하면 슈퍼클래스의 m1
메서드가 실행됩니다.
b = AcListNonSub; c = AcListSub; b.nonSub2(c);
Call m1 via subclass object: Method m1 called
이 동작은 슈퍼클래스의 객체를 대신할 수 있는 서브클래스 객체의 동작과 일치합니다.
액세스 목록이 지정된 추상 메서드
Abstract
로 선언된 메서드를 포함하는 클래스가 추상 클래스입니다. 클래스 정의에 선언된 함수 시그니처를 사용하여 추상 메서드를 구현하는 것이 서브클래스의 역할입니다.
추상 메서드에 액세스 목록이 지정된 경우 액세스 목록에 포함된 클래스만 그 메서드를 구현할 수 있습니다. 액세스 목록에 포함되지 않은 서브클래스는 추상 메서드를 구현할 수 없으므로 해당 서브클래스 자체가 추상 클래스입니다.