% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/class.R
\name{new_class}
\alias{new_class}
\alias{new_object}
\title{Define a new S7 class}
\usage{
new_class(
  name,
  parent = S7_object,
  package = topNamespaceName(parent.frame()),
  properties = list(),
  abstract = FALSE,
  constructor = NULL,
  validator = NULL
)

new_object(.parent, ...)
}
\arguments{
\item{name}{The name of the class, as a string. The result of calling
\code{new_class()} should always be assigned to a variable with this name,
i.e. \code{Foo <- new_class("Foo")}.}

\item{parent}{The parent class to inherit behavior from.
There are three options:
\itemize{
\item An S7 class, like \link{S7_object}.
\item An S3 class wrapped by \code{\link[=new_S3_class]{new_S3_class()}}.
\item A base type, like \link{class_logical}, \link{class_integer}, etc.
}}

\item{package}{Package name. This is automatically resolved if the class is
defined in a package, and \code{NULL} otherwise.

Note, if the class is intended for external use, the constructor should be
exported. Learn more in \code{vignette("packages")}.}

\item{properties}{A named list specifying the properties (data) that
belong to each instance of the class. Each element of the list can
either be a type specification (processed by \code{\link[=as_class]{as_class()}}) or a
full property specification created \code{\link[=new_property]{new_property()}}.}

\item{abstract}{Is this an abstract class? An abstract class can not be
instantiated.}

\item{constructor}{The constructor function. In most cases, you can rely
on the default constructor, which will generate a function with one
argument for each property.

A custom constructor should call \code{new_object()} to create the S7 object.
The first argument, \code{.data}, should be an instance of the parent class
(if used). The subsequent arguments are used to set the properties.}

\item{validator}{A function taking a single argument, \code{self}, the object
to validate.

The job of a validator is to determine whether the object is valid,
i.e. if the current property values form an allowed combination. The
types of the properties are always automatically validated so the job of
the validator is to verify that the \emph{values} of individual properties are
ok (i.e. maybe a property should have length 1, or should always be
positive), or that the \emph{combination} of values of multiple properties is ok.
It is called after construction and whenever any property is set.

The validator should return \code{NULL} if the object is valid. If not, it
should return a character vector where each element describes a single
problem, using \verb{@prop_name} to describe where the problem lies.

See \code{validate()} for more details, examples, and how to temporarily
suppress validation when needed.}

\item{.parent, ...}{Parent object and named properties used to construct the
object.}
}
\value{
A object constructor, a function that can be used to create objects
of the given class.
}
\description{
A class specifies the properties (data) that each of its objects will
possess. The class, and its parent, determines which method will be used
when an object is passed to a generic.

Learn more in \code{vignette("classes-objects")}
}
\examples{
# Create an class that represents a range using a numeric start and end
Range <- new_class("Range",
  properties = list(
    start = class_numeric,
    end = class_numeric
  )
)
r <- Range(start = 10, end = 20)
r
# get and set properties with @
r@start
r@end <- 40
r@end

# S7 automatically ensures that properties are of the declared types:
try(Range(start = "hello", end = 20))

# But we might also want to use a validator to ensure that start and end
# are length 1, and that start is < end
Range <- new_class("Range",
  properties = list(
    start = class_numeric,
    end = class_numeric
  ),
  validator = function(self) {
    if (length(self@start) != 1) {
      "@start must be a single number"
    } else if (length(self@end) != 1) {
      "@end must be a single number"
    } else if (self@end < self@start) {
      "@end must be great than or equal to @start"
    }
  }
)
try(Range(start = c(10, 15), end = 20))
try(Range(start = 20, end = 10))

r <- Range(start = 10, end = 20)
try(r@start <- 25)
}
