Main Content

함께 작동하는 클래스 개발하기

클래스 작성하기

이 예제에서는 이벤트 및 리스너를 통해 상호 작용하는 두 클래스의 설계와 구현에 대한 접근법을 다룹니다. 두 클래스는 은행 계좌와 계좌 관리자를 나타냅니다.

은행 계좌를 나타내는 클래스를 설계하려면 먼저 데이터 요소와 은행 계좌의 추상화를 이루는 연산을 결정해야 합니다. 예를 들어, 은행 계좌에는 다음이 포함됩니다.

  • 계좌 번호

  • 계좌 잔고

  • 상태(개설됨, 해지됨 등)

은행 계좌에 대해서는 다음과 같은 특정 연산을 수행해야 합니다.

  • 각 은행 계좌에 대한 객체 생성

  • 입금

  • 출금

  • 입출금 내역서 생성

  • BankAccount 객체 저장 및 불러오기

잔고가 너무 적은데 출금하려고 하면 은행 계좌에서 알림을 브로드캐스트합니다. 이 이벤트가 발생하면 은행 계좌에서 이러한 알림을 수신 대기하도록 설계된 다른 엔터티에 알림을 브로드캐스트합니다. 이 예제에서는 간소화된 계좌 관리자 프로그램이 이 작업을 수행합니다.

이 예제에서는 계좌 관리자 프로그램이 모든 은행 계좌 상태를 결정합니다. 이 프로그램은 계좌 잔고를 모니터링하여 다음 세 값 중 하나를 할당합니다.

  • open — 계좌 잔고가 양수입니다.

  • overdrawn — 계좌 잔고가 초과 인출되었지만, 초과 인출액이 200달러 이하입니다.

  • closed — 계좌 잔고 초과 인출액이 200달러를 초과합니다.

이러한 특징은 BankAccount 클래스와 AccountManager 클래스의 요구 사항을 정의합니다. 특정한 목적을 충족하는 데 필요한 기능만 포함해야 합니다. BankAccount를 서브클래스화하고 더욱 구체적인 특징을 서브클래스에 추가하여 특수한 유형의 계좌를 지원하도록 합니다. 새 계좌 유형을 지원하는 데 필요한 경우 AccountManager를 확장합니다.

클래스 컴포넌트 지정하기

클래스는 속성에 데이터를 저장하고, 메서드로 연산을 구현하며, 이벤트와 리스너로 알림을 지원합니다. BankAccount 클래스와 AccountManager 클래스가 이러한 컴포넌트를 정의하는 방법은 다음과 같습니다.

클래스 데이터

클래스는 계좌 번호, 계좌 잔고, 계좌 상태를 저장하기 위해 다음 속성을 정의합니다.

  • AccountNumber — 특정 계좌를 식별하는 번호를 저장하는 속성입니다. 사용자가 클래스의 인스턴스를 생성하면 MATLAB®이 이 속성에 값을 할당합니다. BankAccount 클래스 메서드만 이 속성을 설정할 수 있습니다. SetAccess 특성은 private입니다.

  • AccountBalance — 현재 계좌 잔고를 저장하는 속성입니다. 입금 및 출금에 대한 클래스 연산이 이 속성에 값을 할당합니다. BankAccount 클래스 메서드만 이 속성을 설정할 수 있습니다. SetAccess 특성은 private입니다.

  • AccountStatusBankAccount 클래스는 이 속성의 디폴트 값을 정의합니다. AccountManager 클래스 메서드는 AccountBalance의 값이 0 밑으로 떨어질 때마다 이 값을 변경합니다. Access 특성은 AccountManager 클래스와 BankAccount 클래스만 이 속성에 액세스할 수 있도록 지정합니다.

  • AccountListenerInsufficientFunds 이벤트 리스너에 대한 저장소입니다. BankAccount 객체를 저장해도 이 속성은 저장되지 않습니다. 그 이유는 객체를 불러올 때 리스너를 다시 생성해야 하기 때문입니다.

클래스 연산

다음 메서드는 클래스 작성 시에 정의된 연산을 구현합니다.

  • BankAccount — 계좌 번호와 초기 잔고를 받아 계좌를 나타내는 객체를 생성합니다.

  • deposit — 입금 거래가 발생하면 AccountBalance 속성을 업데이트합니다.

  • withdraw — 출금 거래가 발생하면 AccountBalance 속성을 업데이트합니다.

  • getStatement — 계좌에 대한 정보를 표시합니다.

  • loadobj — MAT 파일에서 객체를 불러오면 계좌 관리자 리스너를 다시 생성합니다.

클래스 이벤트

계좌 관리자 프로그램은 잔고가 음수인 은행 계좌의 상태를 변경합니다. 이 동작을 구현하기 위해, 출금으로 인해 잔고가 음수가 되는 경우 BankAccount 클래스가 이벤트를 트리거합니다. 따라서, InsufficientFunds 이벤트의 트리거 동작은 withdraw 메서드 내에서 일어납니다.

이벤트를 정의하려면 events 블록 내에서 이름을 지정해야 합니다. notify 핸들 클래스 메서드에 대한 호출로 이벤트를 트리거하십시오. InsufficientFunds는 미리 정의된 이벤트가 아니기 때문에 임의의 char형 벡터로 이름을 지정하고 임의의 동작으로나 트리거할 수 있습니다.

BankAccount 클래스 구현

BankAccount 클래스의 객체와 연결된 데이터 세트는 하나만 있어야 합니다. 예를 들어, 어떤 계좌 잔고에 대해 서로 다른 값을 가질 수 있는 복수의 객체 복사본이 있어서는 안됩니다. 따라서 BankAccount 클래스를 핸들 클래스로 구현해야 합니다. 주어진 핸들 객체의 모든 복사본은 동일한 데이터를 참조합니다.

BankAccount 클래스 개요

BankAccount 클래스설명
classdef BankAccount < handle

BankAccount의 인스턴스에 대한 복사본이 하나만 있어야 하므로 핸들 클래스입니다.핸들 클래스와 값 클래스 비교

   properties (Access = ?AccountManager)
        AccountStatus = 'open'
   end

AccountStatus는 현재 잔고에 따라 결정되는 계좌의 상태를 포함합니다. 액세스는 BankAccount 클래스와 AccountManager 클래스로 제한됩니다. 클래스 멤버 액세스

   properties (SetAccess = private)
      AccountNumber
      AccountBalance
   end
   properties (Transient)
      AccountListener
   end

AccountManager 클래스 메서드에 의한 AccountStatus 속성 액세스입니다.

AccountNumber 속성과 AccountBalance 속성은 프라이빗 set 액세스를 가집니다.

AccountListener property는 과도형(Transient)이므로 리스너 핸들이 저장되지 않습니다.

속성 특성(Attribute) 항목을 참조하십시오.

   events
      InsufficientFunds
   end

클래스는 InsufficientFunds라는 이벤트를 정의합니다. withdraw 메서드는 계좌 잔고가 음수가 되면 이벤트를 트리거합니다.

이벤트와 리스너에 대한 자세한 내용은 이벤트 항목을 참조하십시오.

   methods

일반 메서드의 블록입니다. 구문은 메서드 구문 항목을 참조하십시오.

      function BA = BankAccount(AccountNumber,InitialBalance)
         BA.AccountNumber = AccountNumber;
         BA.AccountBalance = InitialBalance;
         BA.AccountListener = AccountManager.addAccount(BA);
      end

생성자는 입력 인수로 속성값을 초기화합니다.

AccountManager.addAccountAccountManager 클래스의 정적 메서드입니다. InsufficientFunds 이벤트에 대한 리스너를 생성하고 AccountListener 속성에 리스너 핸들을 저장합니다.

      function deposit(BA,amt)
         BA.AccountBalance = BA.AccountBalance + amt;
         if BA.AccountBalance > 0
            BA.AccountStatus = 'open';
         end
      end

depositAccountBalance 속성값을 조정합니다.

AccountStatusclosed인 경우, 이후에 입금을 통해 AccountBalance가 양수가 되면 AccountStatusopen으로 재설정됩니다.

      function withdraw(BA,amt)
         if (strcmp(BA.AccountStatus,'closed')&& ...
            BA.AccountBalance < 0)
            disp(['Account ',num2str(BA.AccountNumber),...
               ' has been closed.'])
            return
         end
         newbal = BA.AccountBalance - amt;
         BA.AccountBalance = newbal;
         if newbal < 0
            notify(BA,'InsufficientFunds')
         end
      end

AccountBalance 속성을 업데이트합니다. 출금의 결과로 계좌 잔고의 값이 음수가 되면 notifyInsufficientFunds 이벤트를 트리거합니다.

리스너에 대한 자세한 내용은 이벤트와 리스너 구문 항목을 참조하십시오.

      function getStatement(BA)
         disp('-------------------------')
         disp(['Account: ',num2str(BA.AccountNumber)])
         ab = sprintf('%0.2f',BA.AccountBalance);
         disp(['CurrentBalance: ',ab])
         disp(['Account Status: ',BA.AccountStatus])
         disp('-------------------------')
      end
   end

계좌에 대해 선택된 정보를 표시합니다. 이 섹션은 또한 일반 methods 블록의 끝입니다.

   methods (Static)

정적 methods 블록의 시작입니다. 정적 메서드 항목을 참조하십시오.

      function obj = loadobj(s)
         if isstruct(s)
            accNum = s.AccountNumber;
            initBal = s.AccountBalance;
            obj = BankAccount(accNum,initBal);
         else
            obj.AccountListener = AccountManager.addAccount(s);
         end
      end

loadobj 메서드:

  • 불러오기 작업이 실패하면 struct에서 객체를 생성합니다.

  • 새로 생성된 BankAccount 객체를 소스로 사용하여 리스너를 다시 생성합니다.

객체를 저장하고 불러오는 방법에 대한 자세한 내용은 객체에 대한 저장 및 불러오기 프로세스 항목을 참조하십시오.

   end
end

정적 methods 블록의 끝입니다.

classdef의 끝입니다.

 확장하여 클래스 코드 보기

AccountManager 클래스 작성하기

AccountManager 클래스의 용도는 계좌에 서비스를 제공하는 것입니다. BankAccount 클래스에 대해서, AccountManager 클래스는 잔고를 음수로 떨어뜨리는 출금에 대해 수신 대기합니다. BankAccount 객체가 InsufficientFunds 이벤트를 트리거하면 AccountManager가 계좌 상태를 재설정합니다.

AccountManager 클래스는 데이터를 저장하지 않으므로 속성이 필요하지 않습니다. BankAccount 객체는 리스너 객체의 핸들을 저장합니다.

AccountManager는 다음과 같은 두 작업을 수행합니다.

  • 출금의 결과로 발생하는 상태를 각 계좌에 할당

  • 계좌 잔고를 모니터링하여 시스템에 계좌 추가

클래스 컴포넌트

AccountManager 클래스는 다음과 같은 두 메서드를 구현합니다.

  • assignStatusBankAccount 객체에 상태를 할당하는 메서드입니다. 리스너 콜백 역할을 합니다.

  • addAccountInsufficientFunds 리스너를 생성하는 메서드입니다.

AccountManager 클래스 구현하기

AccountManager 클래스는 AccountManager 객체가 필요하지 않기 때문에 두 메서드를 모두 정적 메서드로 구현합니다. 이러한 메서드는 BankAccount 객체에 대해 연산을 수행합니다.

AccountManager는 인스턴스화하는 용도로는 쓰지 마십시오. AccountManager 클래스의 기능을 BankAccount 클래스와 분리하면 유연성과 확장성이 향상됩니다. 예를 들어, 클래스의 기능을 분리하면 다음과 같은 작업을 수행할 수 있습니다.

  • 개별 계좌 클래스를 단순하면서도 특화되도록 유지하면서 다른 유형의 계좌를 지원하도록 AccountManager 클래스를 확장할 수 있습니다.

  • 저장하고 불러온 BankAccount 객체의 호환성에 영향을 주지 않고 계좌 상태의 조건을 변경할 수 있습니다.

  • 각 서브클래스에서 계좌 관리 기능을 구현하도록 하지 않고도 모든 계좌에 공통적인 특징을 추출하는 Account 슈퍼클래스를 개발할 수 있습니다.

AccountManager 클래스 개요

AccountManager 클래스설명
classdef AccountManager

이 클래스는 InsufficentFunds 이벤트 리스너와 리스너 콜백을 정의합니다.

   methods (Static)

이 클래스의 인스턴스를 생성할 필요가 없으므로 정적 메서드가 정의됩니다. 정적 메서드를 참조하십시오.

   function assignStatus(BA)
      if BA.AccountBalance < 0
         if BA.AccountBalance < -200
            BA.AccountStatus = 'closed';
         else
            BA.AccountStatus = 'overdrawn';
         end
      end
   end

assignStatus 메서드는 InsufficentFunds 이벤트 리스너의 콜백입니다. 이 메서드는 AccountBalance 속성값에 따라 BankAccount 객체의 AccountStatus 속성값을 결정합니다.

BankAccount 클래스 생성자는 AccountManager addAccount 메서드를 호출하여 이 리스너를 생성하고 저장합니다.

   function lh = addAccount(BA)
      lh = addlistener(BA, 'InsufficientFunds', ...
         @(src, ~)AccountManager.assignStatus(src));
   end

addAccountBankAccount 클래스가 정의하는 InsufficentFunds 이벤트의 리스너를 생성합니다.

리스너 라이프사이클 제어하기 항목을 참조하십시오.

   end
end

methodsclassdefend 문입니다.

 확장하여 클래스 코드 보기

BankAccount 객체 사용

BankAccount 클래스는 아주 단순하지만 MATLAB 클래스의 동작을 보여줍니다. 예를 들어, 계좌 번호와 초기 입금액 500달러를 사용하여 BankAccount 객체를 생성해 보겠습니다.

BA = BankAccount(1234567,500)
BA = 

  BankAccount with properties:

      AccountNumber: 1234567
     AccountBalance: 500
    AccountListener: [1x1 event.listener]

getStatement 메서드를 사용하여 상태를 검사합니다.

getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: 500.00
Account Status: open
-------------------------

600달러를 출금하여 계좌 잔고가 음수가 되게 합니다.

withdraw(BA,600)
getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: -100.00
Account Status: overdrawn
-------------------------

600달러를 출금한 결과로, InsufficientFunds 이벤트가 트리거되었습니다. AccountManager 클래스로 정의된 현재 조건에 따라 상태가 overdrawn이 됩니다.

200달러를 다시 출금합니다.

withdraw(BA,200)
getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: -300.00
Account Status: closed
-------------------------

이제 리스너에 의해 AccountStatusclosed로 설정되었으며 이후에 출금을 시도할 경우 이벤트가 트리거되지 않고 시도가 차단됩니다.

withdraw(BA,100)
Account 1234567 has been closed.

입금으로 인해 AccountBalance가 양수 값으로 돌아가면 AccountStatus가 open으로 돌아가고 출금이 다시 허용됩니다.

deposit(BA,700)
getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: 400.00
Account Status: open
-------------------------