"Objects model data in Factor. Objects have unique identity, and either hold intrinsic value -- for example, an integer object -- or are composed from named slots, each slot holding an object."
{ $subsection "equality" }
{ $subsection "generic" }
{ $subsection "classes" }
{ $subsection "tuples" } ;
ARTICLE: "equality" "Equality and comparison testing"
"There are two distinct notions of ``sameness'' when it comes to objects. You can test if two references point to the same object, or you can test if two objects are equal in some sense, usually by being instances of the same class, and having equal slot values. Both notions of equality are equality relations in the mathematical sense."
{ $subsection eq? }
{ $subsection = }
"Some types of objects also have an intrinsic order allowing sorting using " { $link natural-sort } ":"
{ $subsection <=> }
"An object can be cloned; the clone has distinct identity but equal value:"
{ $subsection clone } ;
ARTICLE: "generic" "Generic words and methods"
"A generic word's behavior depends on the class of the object at the top of the stack, although this can be generalized using custom method combination. A specific behavior of a generic word on a class is called a " { $emphasis "method" } "."
$terpri
"The key advantage of a generic word over a set of conditional tests is that methods are defined in a decentralized manner, thus adding new methods does not force unnecessary coupling between code."
$terpri
"In the overwhelming majority of cases, your interaction with the generic word system centers on two parsing words:"
"It is possible that two classes have a non-empty intersectionand neither is a subclass of the other. This means there is no canonical linear ordering of classes."
$terpri
"Consider the following set of definitions:"
{ $code
"GENERIC: explain"
"M: general-t explain drop \"a true value\" print ;"
"M: immediate explain drop \"a tagged immediate\" print ;"
"M: object explain drop \"an object\" print ;"
}
"Neither " { $link general-t } " nor " { $link immediate } " are subclasses of each other, yet their intersection is the non-empty " { $link POSTPONE: f } " class. So the generic word system will place " { $link object } " first in the method order, however either " { $link general-t } " or " { $link immediate } " may come next, and it is pretty much a random choice that depends on hashing:"
{ $example "\\ bar order ." "{ object general-list general-t }" }
"Therefore, the outcome of calling " { $snippet "bar" } " with " { $link f } " on the stack is undefined."
$terpri
"As you can see above, the " { $link order } " word can be useful to clarify method dispatch."
"Abstractly, a generic word can be thought of as a big chain of type conditional tests applied to the top of the stack, with methods as the bodies of each test. The " { $emphasis "method combination" } " is this control flow glue between the set of methods, and several aspects of it can be customized:"
{ $list
"which stack item(s) the generic word dispatches upon,"
"which methods out of the set of applicable methods are called"
"The " { $link POSTPONE: GENERIC: } " parsing word creates a generic word using the " { $emphasis "simple method combination" } ". Most generic words that come up in practice use this method combination:"
"Developing a custom method combination requires a good understanding of higher-order programming (code that writes code) and Factor internals. Custom method combination has not been fully explored at this stage of Factor development, and this section can only give a brief sketch of what is involved."
$terpri
"A method combination quotation has stack effect " { $snippet "( word -- quot )" } "."
"A class is a set of objects on which generic words can specialize methods. Classes are organized into a general partial order, and an object may be an instance of more than one class."
$terpri
"You can ask an object for its class:"
{ $subsection class }
"Each class has a membership predicate named after the class with a \"?\" suffix, with the following two exceptions:"
{ { $link general-t } " - there is no need for a predicate word, since the " { $link if } " combinator makes an implicit test for instances of this class" }
"An object is an instance of a union class if it is an instance of one of its members. Union classes are used to associate the same method with several different classes, as well as to conveniently define predicates."
{ $subsection POSTPONE: UNION: }
{ $subsection define-union }
{ $subsection union } ;
ARTICLE: "predicates" "Predicate classes"
"Predicate classes allow fine-grained control over method dispatch."
"This defines a class word named " { $snippet "person" } ", along with a predicate " { $snippet "person?" } ", a default constructor " { $snippet "<person>" } ", and the following reader/writer words:"
ARTICLE: "tuple-constructors" "Constructors and slots"
"New instances of tuple classes are created by calling a constructor word, whose name is the tuple's name surrounded by angle brackets:"
{ $code "TUPLE: point x y z ;\n1 2 3 <point>" }
"The default constructor stores stack elements into consecutive slots, with the top of the stack going into the rightmost slot."
$terpri
"After construction, slots are read and written using various automatically-defined words with names of the form " { $snippet { $emphasis "class-slot" } } " and " { $snippet "set-" { $emphasis "class-slot" } } "."
"If a generic word having the " { $link standard-combination } " method combination is called on a tuple for which it does not have an applicable method, the method call is forwarded to the tuple's " { $emphasis "delegate" } ". If no delegate is set, a " { $link no-method } " error is thrown."
{ $subsection delegate }
{ $subsection set-delegate }
"A tuple's delegate should either be another tuple, or " { $link f } ", indicating no delegate is set. Delegation from a tuple to an object of some other type is not fully supported and should be used with caution."
"Factor uses delegation in place of implementation inheritance, but it is not a direct substitute; in particular, the semantics differ in that a delegated method call receives the delegate on the stack, not the original object."