[R] How to create a proper S4 class?

Martin Morgan
Wed, 17 Nov 2021 15:48:45 -0000

Hi Leonard --

Remember that a class can have 'has a' and 'is a' relationships.
For instance, a People class might HAVE slots name and age

.People <- setClass(
    "People",
    slots = c(name = "character", age = "numeric")
)

while an Employees class might be described as an 'is a' relationship --
all employeeds are people -- while also having slots like years_of_employment
and job_title

.Employees <- setClass(
    "Employees",
    contains = "People",
    slots = c(years_of_employment = "numeric", job_title =
"character")
)

I've used .People and .Employees to capture the return value of setClass(),
and these can be used as constructors

people <- .People(
   name = c("Simon", "Andre"),
   age = c(30, 60)
)

employees = .Employees(
    people, # unnamed arguments are class(es) contained in 'Employees'
    years_of_employment = c(3, 30),
    job_title = c("hard worker", "manager")
)

I would not suggest using attributes in addition to slots. Rather, embrace the
paradigm and represent attributes as additional slots. In practice it is often
helpful to write a constructor function that might transform between formats
useful for users to formats useful for programming, and that can be easily
documented.

Employees <-
    function(name, age, years_of_employment, job_title)
{
    ## implement sanity checks here, or in validity methods
    people <- .People(name = name, age = age)
    .Employees(people, years_of_employment = years_of_employment, job_title =
job_title)
}

plot() and lines() are both S3 generics, and the rules for S3 generics using S4
objects are described in the help page ?Methods_for_S3. Likely you will want to
implement a show() method; show() is an S4 method, so see ?Methods_Details.
Typically this should use accessors rather than relying on direct slot access,
e.g.,

person_names <- function(x) x at name
employee_names <- person_names

The next method implemented is often the [ (single bracket subset) function;
this is relatively complicated to get right, but worth exploring.

I hope that gets you a little further along the road.

Martin Morgan

?On 11/16/21, 11:34 PM, "R-help on behalf of Leonard Mada via R-help"
<r-help-bounces at r-project.org on behalf of r-help at r-project.org>
wrote:

    Dear List-Members,


    I want to create an S4 class with 2 data slots, as well as a plot and a
    line method.


    Unfortunately I lack any experience with S4 classes. I have put together
    some working code - but I presume that it is not the best way to do it.
    The actual code is also available on Github (see below).


    1.) S4 class
    - should contain 2 data slots:
    Slot 1: the agents:
      = agentMatrix class (defined externally, NetlogoR S4 class);
    Slot 2: the path traveled by the agents:
       = a data frame: (x, y, id);
      - my current code: defines only the agents ("t");
    setClass("agentsWithPath", contains =
c(t="agentMatrix"));

    1.b.) Attribute with colors specific for each agent
    - should be probably an attribute attached to the agentMatrix and not a
    proper data slot;
    Note:
    - it is currently an attribute on the path data.frame, but I will
    probably change this once I get the S4 class properly implemented;
    - the agentMatrix does NOT store the colors (which are stored in another
    class - but it is useful to have this information available with the
    agents);

    2.) plot & line methods for this class
    plot.agentsWithPath;
    lines.agentsWithPath;


    I somehow got stuck with the S4 class definition. Though it may be a
    good opportunity to learn about S4 classes (and it is probably better
    suited as an S4 class than polynomials).


    The GitHub code draws the agents, but was somehow hacked together. For
    anyone interested:

    https://github.com/discoleo/R/blob/master/Stat/ABM.Models.Particles.R


    Many thanks,


    Leonard

    ______________________________________________
    R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
    https://stat.ethz.ch/mailman/listinfo/r-help
    PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
    and provide commented, minimal, self-contained, reproducible code.