수색…


클래스 정의하기

클래스는 클래스와 동일한 이름을 가진 .m 파일의 classdef 를 사용하여 정의 할 수 있습니다. 이 파일은 classdef ... end 블록과 클래스 메소드 내에서 사용할 로컬 함수를 포함 할 수 있습니다.

가장 일반적인 MATLAB 클래스 정의의 구조는 다음과 같습니다.

classdef (ClassAttribute = expression, ...) ClassName < ParentClass1 & ParentClass2 & ...

   properties (PropertyAttributes) 
      PropertyName
   end 

   methods (MethodAttributes) 
      function obj = methodName(obj,arg2,...)
         ...
      end
   end

   events (EventAttributes) 
      EventName
   end

   enumeration
      EnumName
   end

end

MATLAB 문서 : 클래스 속성 , 속성 속성 , 메소드 속성 , 이벤트 속성 , 열거 클래스 제한

예제 수업 :

Car 라는 클래스는 Car.m 파일에서 Car.m 과 같이 정의 할 수 있습니다.

classdef Car < handle % handle class so properties persist
    properties
        make
        model
        mileage = 0;
    end

    methods
        function obj = Car(make, model)
            obj.make = make;
            obj.model = model;
        end
        function drive(obj, milesDriven)
            obj.mileage = obj.mileage + milesDriven;
        end
    end
end

생성자는 클래스와 이름이 같은 메서드입니다. <생성자 (constructor)는 객체 지향 프로그래밍에서 클래스 또는 구조의 특수한 메소드로, 그 객체의 객체를 초기화합니다. 생성자는 일반적으로 클래스와 이름이 같은 인스턴스 메서드이며 객체의 멤버 값을 기본값 또는 사용자 정의 값으로 설정하는 데 사용할 수 있습니다.>

이 클래스의 인스턴스는 생성자를 호출하여 만들 수 있습니다.

>> myCar = Car('Ford', 'Mustang'); //creating an instance of car class 

drive 메소드를 호출하면 마일리지가 증가합니다.

>> myCar.mileage 
    
    ans = 
            0

>> myCar.drive(450);

>> myCar.mileage
    
   ans = 
            450

값 대 핸들 클래스

MATLAB의 클래스는 값 클래스와 핸들 클래스의 두 가지 주요 범주로 나뉩니다. 주요 차이점은 값 클래스의 인스턴스를 복사 할 때 기본 데이터가 새 인스턴스에 복사되는 반면 핸들 클래스의 경우 새 인스턴스가 원본 데이터를 가리키고 새 인스턴스의 값을 변경하면 원본 인스턴스가 변경된다는 것입니다. 클래스는 handle 클래스에서 상속하여 핸들로 정의 할 수 있습니다.

classdef valueClass
    properties
        data
    end
end

classdef handleClass < handle
    properties
        data
    end
end

그때

>> v1 = valueClass;
>> v1.data = 5;
>> v2 = v1;
>> v2.data = 7;
>> v1.data
ans =
     5

>> h1 = handleClass;
>> h1.data = 5;
>> h2 = h1;
>> h2.data = 7;
>> h1.data
ans =
     7

클래스와 추상 클래스로부터 상속

면책 조항 : 여기에 제시된 예제는 추상적 인 클래스와 상속의 사용을 보여주기위한 목적 일뿐 실제적으로 사용하지는 않습니다. 또한 MATLAB에는 다형성이 없으므로 추상 클래스의 사용이 제한됩니다. 이 예제는 클래스를 생성하고 다른 클래스에서 상속받으며 추상 클래스를 적용하여 공통 인터페이스를 정의하는 사람을 보여줍니다.

추상 클래스의 사용은 MATLAB에서 다소 제한적이지만 여전히 몇 가지 경우에 유용 할 수 있습니다.

메시지 로거를 원한다고 가정 해 봅시다. 아래와 비슷한 클래스를 만들 수 있습니다.

classdef ScreenLogger
    properties(Access=protected)
        scrh;
    end
    
    methods
        function obj = ScreenLogger(screenhandler)
            obj.scrh = screenhandler;
        end
        
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                fprintf(obj.scrh, '%s\n', sprintf(varargin{:}));
            end
        end
    end
end

속성 및 메서드

즉, 속성은 객체의 상태를 유지하는 반면 메소드는 인터페이스와 같으며 객체에 대한 동작을 정의합니다.

속성 scrh 가 보호됩니다. 이것이 생성자에서 초기화되어야하는 이유입니다. 이 속성에 액세스하는 다른 메서드 (getter)가 있지만이 예제에는 맞지 않습니다. 속성과 메소드는 도트 표기법 다음에 메소드 나 속성의 이름을 사용하여 객체에 대한 참조를 보유하는 변수를 통해 액세스 할 수 있습니다.

mylogger = ScreenLogger(1);                         % OK
mylogger.LogMessage('My %s %d message', 'very', 1); % OK
mylogger.scrh = 2;                                  % ERROR!!! Access denied

속성과 메서드는 public, private 또는 protected가 될 수 있습니다. 이 경우 protected는 상속 된 클래스에서 scrh 에 액세스 할 수 있지만 외부에서는 액세스 할 수 없음을 의미합니다. 기본적으로 모든 속성과 메서드는 public입니다. 따라서 LogMessage() 는 클래스 정의 외부에서 자유롭게 사용할 수 있습니다. 또한 LogMessage 는 객체가 사용자 정의 메시지를 기록 할 때 호출해야하는 인터페이스를 정의합니다.

신청

내 로거를 활용하는 스크립트가 있다고 가정 해 보겠습니다.

clc;
% ... a code
logger = ScreenLogger(1);
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');

동일한 로거를 사용하는 곳이 여러 곳이고 파일에 메시지를 쓰는 것과 같이 좀 더 정교한 것으로 변경하고 싶다면 다른 객체를 만들어야합니다.

classdef DeepLogger
    properties(SetAccess=protected)
        FileName
    end
    methods
        function obj = DeepLogger(filename)
            obj.FileName = filename;
        end
        
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                fid = fopen(obj.fullfname, 'a+t');
                fprintf(fid, '%s\n', sprintf(varargin{:}));
                fclose(fid);
            end
        end
    end 
end

한 줄의 코드를 다음과 같이 변경하십시오.

clc;
% ... a code
logger = DeepLogger('mymessages.log');

위의 방법은 단순히 파일을 열고, 파일의 끝에 메시지를 추가하고 닫습니다. 현재로서는 인터페이스와 일관성을 유지하기 위해 메서드의 이름은 LogMessage() 이지만 다른 것과 똑같이 사용할 수 있음을 기억해야합니다. MATLAB은 추상 클래스를 사용하여 developper가 동일한 이름을 사용하도록 강제 할 수 있습니다. 로거에 대한 공통 인터페이스를 정의한다고 가정 해 보겠습니다.

classdef MessageLogger
    methods(Abstract=true)
        LogMessage(obj, varargin);
    end
end

이제 ScreenLoggerDeepLogger 클래스에서 상속되면 LogMessage() 가 정의되지 않은 경우 MATLAB에서 오류가 발생합니다. 추상 클래스는 동일한 인터페이스를 사용할 수있는 유사한 클래스를 작성하는 데 도움이됩니다.

이 예시를 위해서, 나는 약간 다른 변화를 만들 것이다. DeepLogger가 동시에 화면에 메시지와 파일을 동시에 기록한다고 가정 할 것입니다. 때문에 ScreenLogger 이미 화면에 메시지를 기록, 나는 상속 하겠어 DeepLogger 으로부터 ScreenLoggger 반복을 피하기 위해. ScreenLogger 는 첫 번째 줄을 제외하고 전혀 변경되지 않습니다.

classdef ScreenLogger < MessageLogger
// the rest of previous code 

그러나 DeepLoggerLogMessage 메소드에서 더 많은 변경이 필요합니다.

classdef DeepLogger < MessageLogger & ScreenLogger
    properties(SetAccess=protected)
        FileName
        Path
    end
    methods
        function obj = DeepLogger(screenhandler, filename)
            [path,filen,ext] = fileparts(filename);
            obj.FileName = [filen ext];
            pbj.Path     = pathn;
            obj = obj@ScreenLogger(screenhandler);
        end
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                LogMessage@ScreenLogger(obj, varargin{:});
                fid = fopen(obj.fullfname, 'a+t');
                fprintf(fid, '%s\n', sprintf(varargin{:}));
                fclose(fid);
            end
        end
    end
end

첫째, 나는 단순히 생성자의 속성을 초기화합니다. 둘째,이 클래스는 ScreenLogger 에서 상속 ScreenLogger 때문에이 parrent 객체도 초기화해야합니다. ScreenLogger 생성자는 자체 개체를 초기화하는 데 하나의 매개 변수가 필요하기 ScreenLogger 줄은 훨씬 더 중요합니다. 이 행 :

obj = obj@ScreenLogger(screenhandler);

단순히 "ScreenLogger의 생성자를 호출하고 스크린 핸들러로 초기 화"합니다. scrh 를 보호 된 것으로 정의한 점은 여기서 주목할 가치가 있습니다. 따라서 DeepLogger 에서이 속성에 똑같이 액세스 할 수 있습니다. 특성이 개인으로 정의 된 경우 그것을 초기화하는 유일한 방법은 consuctor를 사용하는 것입니다.

또 다른 변경 사항은 섹션 methods 있습니다. 반복을 피하기 위해 부모 클래스의 LogMessage() 를 호출하여 화면에 메시지를 기록합니다. 스크린 로깅을 개선하기 위해 무엇인가를 변경해야한다면 이제는 한 곳에서해야합니다. 나머지 코드는 DeepLogger 의 일부분과 DeepLogger 합니다.

이 클래스는 추상 클래스 인 MessageLogger 로부터 상속 DeepLogger 내부의 LogMessage() 도 정의되어야합니다. MessageLogger 에서 상속하는 것은 약간 까다 롭습니다. LogMessage 다시 정의해야한다고 생각합니다. 내 추측.

로거가 적용된 코드 측면에서 클래스의 공통 인터페이스 덕분에 전체 코드에서이 한 줄을 변경해도 아무런 문제가 없음을 확신 할 수 있습니다. 동일한 메시지는 이전과 같이 화면에 로그온 할 것이지만 추가로 코드는 이러한 메시지를 파일에 기록합니다.

clc;
% ... a code
logger = DeepLogger(1, 'mylogfile.log');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');

이 예제가 클래스 사용, 상속 사용 및 추상 클래스 사용에 대해 설명하기를 바랍니다.


추신. 위의 문제에 대한 해결책은 많은 것 중 하나입니다. 덜 복잡한 또 다른 솔루션은 ScreenLogerFileLogger 등의 다른 로거의 구성 요소로 ScreenLogger 것입니다. ScreenLogger 는 속성 중 하나에 보관됩니다. LogMessage 는 단순히 ScreenLogger LogMessage 를 호출하고 화면에 텍스트를 표시합니다. MATLAB에서 클래스가 작동하는 방식을 보여주기 위해 좀 더 복잡한 방법을 선택했습니다. 아래의 예제 코드는 다음과 같습니다.

classdef DeepLogger < MessageLogger
    properties(SetAccess=protected)
        FileName
        Path
        ScrLogger
    end
    methods
        function obj = DeepLogger(screenhandler, filename)
            [path,filen,ext] = fileparts(filename);
            obj.FileName     = [filen ext];
            obj.Path         = pathn;
            obj.ScrLogger    = ScreenLogger(screenhandler);
        end
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                obj.LogMessage(obj.ScrLogger, varargin{:}); % <-------- thechange here
                fid = fopen(obj.fullfname, 'a+t');
                fprintf(fid, '%s\n', sprintf(varargin{:}));
                fclose(fid);
            end
        end
    end
end

생성자

생성자 는 객체의 인스턴스가 만들어 질 때 호출되는 클래스의 특수한 메서드입니다. 입력 매개 변수를 받아들이는 정규 MATLAB 함수이지만 특정 규칙을 따라야 합니다.

MATLAB이 기본 생성자를 생성하므로 생성자가 필요하지 않습니다. 그러나 실제로는 객체의 상태를 정의하는 곳입니다. 예를 들어 특성을 지정하여 특성을 제한 할 수 있습니다. 그런 다음 생성자는 기본적으로 생성자의 입력 매개 변수를 통해 전송할 수있는 기본적으로 또는 사용자 정의 값에 의해 이러한 속성을 초기화 할 수 있습니다.

간단한 클래스의 생성자 호출

이것은 간단한 클래스 Person 입니다.

classdef Person
    properties
        name
        surname
        address
    end
    
    methods
        function obj = Person(name,surname,address)
            obj.name = name;
            obj.surname = surname;
            obj.address = address;
        end
    end
end

생성자의 이름은 클래스의 이름과 동일합니다. 따라서 생성자는 클래스 이름으로 호출됩니다. Person 클래스는 다음과 같이 만들 수 있습니다.

>> p = Person('John','Smith','London')
p = 
  Person with properties:

       name: 'John'
    surname: 'Smith'
    address: 'London'

자식 클래스의 생성자 호출

공유 공통 속성 또는 메소드 인 경우 클래스를 부모 클래스에서 상속 할 수 있습니다. 클래스가 다른 클래스에서 상속 될 때, 부모 클래스의 생성자가 호출되어야합니다.

클래스의 Member 클래스에서 상속 Person 때문에 Member Person 클래스와 같은 속성을 사용하지만 그것은 또한 추가 payment 그 정의에.

classdef Member < Person
    properties
        payment
    end

    methods
        function obj = Member(name,surname,address,payment)
            obj = obj@Person(name,surname,address);
            obj.payment = payment;
        end
    end
end

Person 클래스와 마찬가지로 Member 도 생성자를 호출하여 만듭니다.

>> m = Member('Adam','Woodcock','Manchester',20)
m = 
  Member with properties:

    payment: 20
       name: 'Adam'
    surname: 'Woodcock'
    address: 'Manchester'

Person 의 생성자에는 3 개의 입력 매개 변수가 필요합니다. Member 는이 사실을 존중해야하므로 세 개의 매개 변수를 사용하여 Person 클래스의 생성자를 호출해야합니다. 그것은 다음 행에 의해 성취된다.

obj = obj@Person(name,surname,address);

위의 예는 하위 클래스가 상위 클래스에 대한 정보를 필요로하는 경우를 보여줍니다. 이것이 Member 의 생성자가 4 개의 매개 변수를 필요로하는 이유입니다. 3 개는 부모 클래스 용이고 하나는 자체 용 매개 변수입니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow