% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/convert.R
\name{convert}
\alias{convert}
\title{Convert an object from one type to another}
\usage{
convert(from, to, ...)
}
\arguments{
\item{from}{An S7 object to convert.}

\item{to}{An S7 class specification, passed to \code{\link[=as_class]{as_class()}}.}

\item{...}{Other arguments passed to custom \code{convert()} methods. For upcasting,
these can be used to override existing properties or set new ones.}
}
\value{
Either \code{from} coerced to class \code{to}, or an error if the coercion
is not possible.
}
\description{
\code{convert(from, to)} is a built-in generic for converting an object from
one type to another. It is special in three ways:
\itemize{
\item It uses double-dispatch, because conversion depends on both \code{from} and
\code{to}.
\item It uses non-standard dispatch because \code{to} is a class, not an object.
\item It doesn't use inheritance for the \code{to} argument. To understand
why, imagine you have written methods to objects of various types to
\code{classParent}. If you then create a new \code{classChild} that inherits from
\code{classParent}, you can't expect the methods written for \code{classParent}
to work because those methods will return \code{classParent} objects, not
\code{classChild} objects.
}

\code{convert()} provides two default implementations:
\enumerate{
\item When \code{from} inherits from \code{to}, it strips any properties that \code{from}
possesses that \code{to} does not (downcasting).
\item When \code{to} is a subclass of \code{from}'s class, it creates a new object of
class \code{to}, copying over existing properties from \code{from} and initializing
new properties of \code{to} (upcasting).
}

If you are converting an object solely for the purposes of accessing a method
on a superclass, you probably want \code{\link[=super]{super()}} instead. See its docs for more
details.
\subsection{S3 & S4}{

\code{convert()} plays a similar role to the convention of defining \code{as.foo()}
functions/generics in S3, and to \code{as()}/\code{setAs()} in S4.
}
}
\examples{
Foo1 <- new_class("Foo1", properties = list(x = class_integer))
Foo2 <- new_class("Foo2", Foo1, properties = list(y = class_double))

# Downcasting: S7 provides a default implementation for coercing an object
# to one of its parent classes:
convert(Foo2(x = 1L, y = 2), to = Foo1)

# Upcasting: S7 also provides a default implementation for coercing an object
# to one of its child classes:
convert(Foo1(x = 1L), to = Foo2)
convert(Foo1(x = 1L), to = Foo2, y = 2.5)  # Set new property
convert(Foo1(x = 1L), to = Foo2, x = 2L, y = 2.5)  # Override existing and set new

# For all other cases, you'll need to provide your own.
try(convert(Foo1(x = 1L), to = class_integer))

method(convert, list(Foo1, class_integer)) <- function(from, to) {
  from@x
}
convert(Foo1(x = 1L), to = class_integer)

# Note that conversion does not respect inheritance so if we define a
# convert method for integer to foo1
method(convert, list(class_integer, Foo1)) <- function(from, to) {
  Foo1(x = from)
}
convert(1L, to = Foo1)

# Converting to Foo2 will still error
try(convert(1L, to = Foo2))
# This is probably not surprising because foo2 also needs some value
# for `@y`, but it definitely makes dispatch for convert() special
}
