A heterogeneous class hierarchy lets you create arrays containing objects of different classes that are related though inheritance. You can define class methods that operate on these heterogeneous arrays as a whole.
A class design based on heterogeneous arrays provides a more convenient interface than, for example, extracting elements from a cell array and operating on these elements individually. For more information on the design of class hierarchies that support heterogeneous arrays, see Designing Heterogeneous Class Hierarchies.
All heterogeneous hierarchies derive from matlab.mixin.Heterogeneous
.
This example does not use valid terminology or techniques for managing financial assets. The purpose of this example is only to illustrate techniques for defining heterogeneous class hierarchies.
This example implements a system of classes to represent financial assets, such as stocks, bonds, and cash. Classes to represent categories of assets have certain common requirements. Each instance has one of the following:
Textual description
Type (stock, bond, or cash)
Means to determine the current value of the asset
Heterogeneous arrays of these objects need methods that can operate on the whole array. These operations include:
Creating a table of information about all assets contained in the array
Graphing the relative contribution of each asset type contained in the array
These requirements are factored into the class that is the root
of the hierarchy. The root class derives from matlab.mixin.Heterogeneous
.
In the following diagram, the Assets
class is the
root of the hierarchy. The Stocks
, Bonds
,
and Cash
classes provide the specialization required
for each type of asset.
The Assets
class:
Derives directly from matlab.mixin.Heterogeneous
Is the root of the heterogeneous hierarchy
Is abstract
Is the class of heterogeneous arrays composed of any
mixture of Stock
, Bond
, and Cash
objects
The Assets
class defines two properties:
Description
— A general
description of the individual asset constrained to be of class char
.
Type
— The type of asset
defined as an abstract property that each subclass implements.
The Assets
class defines these methods:
pie
— A sealed method that
creates a pie chart showing the relative mix of asset types.
makeReport
— A sealed method
that creates a report listing the assets.
getCurrentValue
— An abstract
method that each concrete subclass must implement to return the current
value of the asset.
getDefaultScalarElement
— matlab.mixin.Heterogeneous
class
method overridden in the Assets
class to specify
a default object. The Assets
class is abstract
so it cannot be used as the default object. For more information,
see Default Object.
Methods defined by the Assets
class are either:
Concrete methods (fully implemented) that subclasses do not override
Abstract methods (signatures only) that subclasses implement
Concrete methods defined by superclasses in a heterogeneous
hierarchy must specify the Sealed
attribute. Sealing
these methods prevents subclasses from overriding methods implemented
by the superclass. When calling methods on a heterogeneous array, MATLAB® calls
the methods defined by the class of the array (Assets
in
this example).
The pie
and makeReport
methods
are examples of sealed methods that operate on heterogeneous arrays
composed of Stock
, Bond
, and Cash
objects.
Abstract methods defined by the superclasses in a heterogeneous
hierarchy must specify the Abstract
attribute.
Defining an abstract method in a superclass ensures that concrete
subclasses have an implementation for that exact method name. Use
these methods element-wise so that each object calls its own method.
The getCurrentValue
method is an example
of an abstract method that is implemented by each subclass to get
the current value of each asset.
Each type of subclass object calculates its current value in
a different way. If you add another category of asset by adding another
subclass to the hierarchy, this class must implement its own version
of a getCurrentValue
method. Because all subclasses
implement a getCurrentValue
method, the pie
and makeReport
methods
work with newly added subclasses.
For more information on the Sealed
and Abstract
method
attributes, see Method Attributes.
The Assets
class and other classes in the
hierarchy are contained in a package called financial
.
classdef Assets < matlab.mixin.Heterogeneous % file: +financial.@Assets/Assets.m properties Description char = 'Assets' end properties (Abstract, SetAccess = private) Type end methods (Abstract) % Not implemented by Assets class value = getCurrentValue(obj) end methods (Static, Sealed, Access = protected) function defaultObject = getDefaultScalarElement defaultObject = financial.DefaultAsset; end end methods (Sealed) % Implemented in separate files % +financial.@Assets/pie.m % +financial.@Assets/makeReport.m pie(assetArray) makeReport(assetArray) end end
For code listings for pie
and makeReport
,
see Operating on an Assets Array.
The Stocks
class represents a specific type
of financial asset. It is a concrete class that implements the abstract
members defined by the Assets
class, and defines
class properties and methods specific to this type of asset.
The Stocks
class defines these properties:
NumShares
— The number of
shares held for this asset.
Symbol
— The ticker symbol
corresponding to this stock.
Type
— Stocks
class
implementation of the abstract property defined by the Assets
class.
This concrete property must use the same attributes as the abstract
version (that is, SetAccess private
).
SharePrice
— Dependent property
for the price per share. The get.SharePrice
method
obtains the current share price from web services when this property
is queried.
The Stocks class defines these methods:
Stocks
— The constructor
assigns property values and supports a default constructor called
with no input arguments.
getCurrentValue
— This method
is the Stocks
class implementation of the abstract
method defined by the Assets
class. It returns
the current value of this asset.
get.SharePrice
— The property
get method for the dependent SharePrice
property
returns the current share price of this stock. For information on
how to access web services from MATLAB, see the webread
function.
classdef Stocks < financial.Assets properties NumShares double = 0 Symbol string end properties (SetAccess = private) Type = "Stocks" end properties (Dependent) SharePrice double end methods function sk = Stocks(description,numshares,symbol) if nargin == 0 description = ''; numshares = 0; symbol = ''; end sk.Description = description; sk.NumShares = numshares; sk.Symbol = symbol; end function value = getCurrentValue(sk) value = sk.NumShares*sk.SharePrice; end function pps = get.SharePrice(sk) % Implement web access to obtain % Current price per share % Returning dummy value pps = 1; end end end
The Bonds
class represents a specific type
of financial asset. It is a concrete class that implements the abstract
members defined by the Assets
class and defines
class properties and methods specific to this type of asset.
The Bonds
class defines these properties:
FaceValue
— Face value of
the bond.
Yield
— Annual interest
rate of the bond.
Type
— Bonds
class
implementation of the abstract property defined by the Assets
class.
This concrete property must use the same attributes as the abstract
version (that is, SetAccess private
).
CurrentYield
— Dependent
property for the current yield, The get.CurrentYield
property
get method obtains the value from web services.
The Bonds
class defines these methods:
Bonds
— The constructor
assigns property values and supports a default constructor called
with no input arguments.
getCurrentVlaue
— This method
is the Bonds
class implementation of the abstract
method defined by the Assets
class. It returns
the current value of this asset.
get.CurrentYield
— The property
get method for the dependent CurrentYield
property
returns the current yield on this bond. For information on how to
access web serviced from MATLAB, see the webread
function.
classdef Bonds < financial.Assets properties FaceValue double = 0 Yield double = 0 end properties (SetAccess = private) Type = "Bonds" end properties (Dependent) CurrentYield double = 0 end methods function b = Bonds(description,facevalue,yield) if nargin == 0 description = ''; facevalue = 0; yield = 0; end b.Description = description; b.FaceValue = facevalue; b.Yield = yield; b.Type = AssetTypes.Bonds; end function mv = getCurrentValue(b) y = b.Yield; cy = b.CurrentYield; if cy <= 0 || y <= 0 mv = b.FaceValue; else mv = b.FaceValue*y/cy; end end function r = get.CurrentYield(b) % Implement web access to obtain % Current yield for this bond % Returning dummy value r = 0.24; end end end
The Cash
class represents a specific type
of financial asset. It is a concrete class that implements the abstract
members defined by the Assets
class and defines
class properties and methods specific to this type of asset.
The Cash
class defines these properties:
Amount
— The amount of cash
held in this asset.
Type
— Cash
class
implementation of the abstract property defined by the Assets
class.
This concrete property must use the same attributes as the abstract
version (that is, SetAccess private
).
The Cash
class defines these methods:
Cash
— The constructor assigns
property values and supports a default constructor called with no
input arguments.
getCurrentValue
— This method
is the Cash
class implementation of the abstract
method defined by the Assets
class. It returns
the current value of this asset.
save
— This method adds
the specified amount of cash to the existing amount and returns a
new Cash
object with the current amount.
spend
— This method deducts
the specified amount from the current amount and returns a new Cash
object
with the current amount.
classdef Cash < financial.Assets properties Amount double = 0 end properties (SetAccess = private) Type = "Cash" end methods function c = Cash(description,amount) if nargin == 0 description = ''; amount = 0; end c.Description = description; c.Amount = amount; end function value = getCurrentValue(c) value = c.Amount; end function c = save(c,amount) newValue = c.Amount + amount; c.Amount = newValue; end function c = spend(c,amount) newValue = c.Amount - amount; if newValue < 0 c.Amount = 0; disp('Your balance is $0.00') else c.Amount = newValue; end end end end
The design of this class hierarchy uses an abstract root class
(Assets
). Therefore, the Assets
class
must specify a concrete class to use as a default object by overriding getDefaultScalarElement
.
In this case, options include:
Use one of the existing concrete classes for the default object.
Define a concrete class in the hierarchy to use for the default object.
This implementation adds the DefaultAsset
class
to the hierarchy as a subclass of the Assets
class. MATLAB creates
objects of this class when:
Creating arrays using indexed assignment with gaps in index numbers
Loading heterogeneous arrays from MAT-files when MATLAB cannot find the class of an array element.
This diagram shows the addition of the DefaultAsset
class:
classdef DefaultAsset < financial.Assets % file: +financial.@DefaultAsset/DefaultAsset.m properties (SetAccess = private) Type = "DefaultAsset" end methods function obj = DefaultAsset obj.Description = 'Place holder'; end function value = getCurrentValue(~) value = 0; end end end
The Assets
class defines these methods to
operate on heterogeneous arrays of asset objects:
pie
— Creates a pie chart
showing the mix of asset types in the array.
makeReport
— Uses the MATLAB table
object to display a table of asset
information.
To operate on a heterogeneous array, a method must be defined
for the class of the heterogeneous array and must be sealed. In this
case, the class of heterogeneous arrays is always the Assets
class. MATLAB does
not use the class of the individual elements of the heterogeneous
array when dispatching to methods.
The Assets
class makeReport
method
builds a table using the common properties and getCurrentValue
method
for each object in the array.
function makeReport(obj) numMembers = length(obj); descs = cell(1,numMembers); types(numMembers) = ""; values(numMembers) = 0; for k = 1:numMembers descs{k} = obj(k).Description; types(k) = obj(k).Type; values(k) = obj(k).getCurrentValue; end t = table; t.Description = descs'; t.Type = types'; t.Value = values'; disp(t) end
The Assets
class pie
method
calls the getCurrentValue
method element-wise on
objects in the array to obtain the data for the pie chart.
function pie(assetArray) stockAmt = 0; bondAmt = 0; cashAmt = 0; for k=1:length(assetArray) if isa(assetArray(k),'financial.Stocks') stockAmt = stockAmt + assetArray(k).getCurrentValue; elseif isa(assetArray(k),'financial.Bonds') bondAmt = bondAmt + assetArray(k).getCurrentValue; elseif isa(assetArray(k),'financial.Cash') cashAmt = cashAmt + assetArray(k).getCurrentValue; end end k = 1; if stockAmt ~= 0 label(k) = {'Stocks'}; pieVector(k) = stockAmt; k = k +1; end if bondAmt ~= 0 label(k) = {'Bonds'}; pieVector(k) = bondAmt; k = k +1; end if cashAmt ~= 0 label(k) = {'Cash'}; pieVector(k) = cashAmt; end pie(pieVector,label) tv = stockAmt + bondAmt + cashAmt; stg = {['Total Value of Assets: $',num2str(tv,'%0.2f')]}; title(stg,'FontSize',10) end
These statements create a heterogeneous array by concatenating
the Stocks
, Bonds
, and Cash
objects.
Calling the makeReport
and pie
methods
creates the output shown.
s = financial.Stocks('Acme Motor Company',100,string('A')); b = financial.Bonds('3 Month T',700,0.3); c(1) = financial.Cash('Bank Account',500); c(2) = financial.Cash('Gold',500); assetArray = [s,b,c]; makeReport(assetArray) pie(assetArray)
Description Type Value ____________________ ______ ______ 'Acme Motor Company' Stocks 1232.5 '3 Month T' Bonds 807.69 'Bank Account' Cash 500 'Gold' Cash 500