Class to Represent Structured Data

Example Code

Open class definition file in the MATLAB editor.Open class definition file in the MATLAB editor. — Use this link if you want to save and modify your version of the class.

To use the class, create a folder named @TensileData and save TensileData.m to this folder. The parent folder of @TensileData must be on the MATLAB® path.

Objects As Data Structures

This example defines a class for storing data with a specific structure. Using a consistent structure for data storage makes it easier to create functions that operate on the data. While a MATLAB struct with field names describing the particular data element is a useful way to organize data, the use of a class to define both the data storage (properties) and operations you can perform on that data (methods) provides advantages, as this example illustrates.

Concepts on Which This Example Is Based.

For purposes of this example, the data represents tensile stress/strain measurements, which are used to calculate the elastic modulus of various materials. In simple terms, stress is the force applied to a material and strain is the resulting deformation. Their ratio defines a characteristic of the material. While this is an over simplification of the process, it suffices for this example.

Structure of the Data

The following table describes the structure of the data.

Data

Description

Material

Character string identifying the type of material tested

SampleNumber

Number of a particular test sample

Stress

Vector of doubles representing the stress applied to the sample during the test.

Strain

Vector of doubles representing the strain at the corresponding values of the applied stress.

Modulus

Double defining an elastic modulus of the material under test, which is calculated from the stress and strain data

The TensileData Class

This class is designed to store data, so it defines a property for each of the data elements. The following class block defines five properties and specifies their initial values according to the type of data each will contain. Defining initial values is not required, but can be useful if a property value is not assigned during object creation.

Note that this example begins with a simple implementation of the class and builds on this implementation to illustrate how features enhance the usefulness of the class.

classdef TensileData
   properties
      Material = '';
      SampleNumber = 0;
      Stress
      Strain
      Modulus = 0;
   end
end

Creating an Instance and Assigning Data

Create a TensileData object and assign data to it with the following statements:

td = TensileData;
td.Material = 'Carbon Steel';
td.SampleNumber = 001;
td.Stress = [2e4 4e4 6e4 8e4];
td.Strain = [.12 .20 .31 .40];
td.Modulus = mean(td.Stress./td.Strain);

Advantages of a Class vs. a Structure Array

Treat the TensileData object (td in the statements above) much as you would any MATLAB structure array. However, defining a specialized data structure as a class has advantages over using a general-purpose data structure, like a MATLAB struct:

  • Users cannot accidentally misspell a field name without getting an error. For example, typing the following:

    >>td.Modulis = ...
    

    would simply add a new field to a structure array, but returns an error when td is an instance of the TensileData class.

  • A class is easy to reuse. Once you have defined the class, you can easily extend it with subclasses that add new properties.

  • A class is easy to identify. A class has a name so that you can identify objects with the whos and class functions and the Workspace browser. The class name makes it easy to refer to records with a meaningful name.

  • A class can validate individual field values when assigned, including class or value.

  • A class can restrict access to fields, for example, allowing a particular field to be read, but not changed.

The next section describes how to add type checking and how to restrict property access in the TensileData class.

Restricting Properties to Specific Values

Restrict the values to which a property can be set by defining a property set access method. MATLAB software then calls this function whenever a value is set for a property, including when creating the object.

Defining the Material Property Set Function

The property set method restricts the assignment of the Material property to one of the following strings: aluminum, stainless steel, or carbon steel.

Add this function definition to the methods block.

classdef TensileData
   properties
      Material = 'carbon steel';
      SampleNumber = 0;
      Stress
      Strain
      Modulus
   end % properties
   methods
      function obj = set.Material(obj,material)
         if ~(strcmpi(material,'aluminum') ||... 
            strcmpi(material,'stainless steel') ||... 
            strcmpi(material,'carbon steel'))
            error('Material must be aluminum, stainless steel, or carbon steel')
         end
      obj.Material = material;
      end % set.Material
   end% methods
end% classdef

When an attempt is made to set the Material property, the MATLAB runtime passes the object and the specified value to the property's set.Material function (the obj and the material input arguments). In this case, if the value does not match the acceptable values, the function returns an error. Otherwise, the specified value is used to set the property. Only the set method can directly access the property in the object (without calling the property set method).

For example:

td = TensileData;
td.Material = 'composite';
Error using TensileData/set.Material
Material must be aluminum, stainless steel, or carbon steel

Simplifying the Interface with a Constructor

You can simplify the interface to the TensileData class by adding a constructor function that:

  • Enables you to pass the data as arguments to the constructor

  • Assigns values to properties

The constructor is a method having the same name as the class.

function td = TensileData(material,samplenum,stress,strain)
   if nargin > 0 % Support calling with 0 arguments
      td.Material = material;
      td.SampleNumber = samplenum;
      td.Stress = stress;
      td.Strain = strain;
   end 
end % TensileData

Using the constructor, you can create a TensileData object fully populated with data using the following statement:

td = TensileData('carbon steel',1,[2e4 4e4 6e4 8e4],[.12 .20 .31 .40]);

Calculating Modulus

Note that the constructor function does not have an input argument for the value of the Modulus property. This is because the value of the Modulus:

  • Is easy to calculate from the Stress and Strain property values

  • Needs to change if the value of the Stress or Strain property changes

Therefore, it is better to calculate the value of the Modulus property only when its value is requested. You can do this with a property get access method, which is described in the next section.

Using a Dependent Property

TensileData objects do not store the value of the Modulus property; instead this value is calculated whenever it is requested. This approach enables you to update the Stress and Strain property data at any time without having to recalculate the value of the Modulus property.

Modulus Property Get Method

The Modulus property depends on Stress and Strain, so its Dependent attribute is set to logical true. To do this, create another properties block to set the Dependent attribute.

Also, because the get.Modulus method calculates and returns the value of the Modulus property, you should set the property's SetAccess attribute to private.

properties (Dependent = true, SetAccess = private)
   Modulus
end

Define the property's get method in a methods block.

methods 
   function modulus = get.Modulus(obj)
      ind = find(obj.Strain > 0); % Find nonzero strain
      modulus = mean(obj.Stress(ind)./obj.Strain(ind)); 
   end % Modulus get method
end % methods

This function simply calculates the average ratio of stress to strain data after eliminating zeros in the denominator data.

The MATLAB runtime calls the get.Modulus method when the property is queried. For example,

td = TensileData('carbon steel',1,[2e4 4e4 6e4 8e4],[.12 .20 .31 .40]);
td.Modulus
ans =
  1.9005e+005

Modulus Property Set Method

To set the value of a Dependent property, the class must implement a property set method. There is no need to enable explicit setting of the Modulus property, but a set method enables you to provide a customized error message. The Modulus set method references the current property value and then returns an error:

methods 
   function obj = set.Modulus(obj,~)
      fprintf('%s%d\n','Modulus is: ',obj.Modulus)
      error('You cannot set Modulus explicitly'); 
   end % Modulus set method
end % methods

Displaying TensileData Objects

The TensileData class can implement a disp method that controls what is displayed when an object of this class is shown on the command line (for example, by an assignment statement not terminated by a semicolon).

The TensileData disp method displays the value of the Material, SampleNumber, and Modulus properties. It does not display the Stress and Strain property data since these properties contain raw data that is not easily viewed in the command window. The plot method (described in the next section) provides a better way to display stress and strain data.

The disp method uses fprintf to display formatted text in the command window:

methods
   function disp(td)
      fprintf(1,'Material: %s\nSample Number: %g\nModulus: %1.5g\n',...
      td.Material,td.SampleNumber,td.Modulus);
   end % disp
end % methods

Method to Plot Stress vs. Strain

It is useful to view a graph of the stress/strain data to determine the behavior of the material over a range of applied tension. A TensileData object contains the stress and strain data so it is useful to define a class method that is designed to plot this data.

The TensileData plot method creates a linear graph of the stress versus strain data and adds a title and axis labels to produce a standardized graph for the tensile data records:

function plot(td,varargin)
   plot(td.Strain,td.Stress,varargin{:})
   title(['Stress/Strain plot for Sample',...
      num2str(td.SampleNumber)])
   ylabel('Stress (psi)')
   xlabel('Strain %')
end % plot

The first argument to this method is a TensileData object, which contains the data and is used by the MATLAB runtime to dispatch to the TensileData class plot method and not the built-in plot function.

The variable list of arguments that follow are passed directly to the built-in plot function from within the method. This enables the TensileData plot method to behave like the built-in plot function, which allows you to pass line specifier arguments or property name/value pairs along with the data.

For example, plotting the following object:

td = TensileData('carbon steel',1,[2e4 4e4 6e4 8e4],[.12 .20 .31 .40]);
plot(td,'-+g','LineWidth',2)

produces this graph.

Was this topic helpful?