1+ # Polymorphic data structures
2+
3+ Sometimes it's required to deal with the collection of records of different types.
4+ In the simplest case, `Record.Collection` is polymirphic in a sense that it may hold any record
5+ inside, as well as the record's attribute of the `Record` type.
6+
7+ The trick, however, is to restore polymorphic data from JSON as its type is unknown.
8+ Type-R solves it with _abstract records_.
9+
10+ ## Defining an abstract record
11+
12+ Record base class with the `create()` factory function attached to its definition is an _abstract record_.
13+
14+ ### `static` create( attrs, options )
15+
16+ The factory function used internally by Type-R to create the instance of the record.
17+ Must be defined in the base class for the polymorphic record.
18+
19+ ```javascript
20+ @define class Widget extends Record {
21+ static attributes = {
22+ type : String
23+ }
24+
25+ static create( attrs, options ){
26+ switch( attrs.type ){
27+ case "typeA" : return new TypeA( attrs, options );
28+ case "typeB" : return new TypeB( attrs, options );
29+ }
30+ }
31+ }
32+
33+ @define class TypeA extends Widget {
34+ static attributes = {
35+ type : "typeA",
36+ ...
37+ }
38+ }
39+
40+ @define class TypeB extends Widget {
41+ static attributes = {
42+ type : "typeB",
43+ ...
44+ }
45+ }
46+ ```
47+
48+ ## Polymorphic attributes and collections
49+
50+ Abstract record type can be used to define serializable polymorphic attributes and collections.
51+
52+ ### `attrDef` attr : PolymorphicRecord
53+
54+ Attribute of polymorphic record type is serializable.
55+
56+ ### PolymorphicRecord.Collection
57+
58+ The default Collection for the polymorphic record type is serializable.
59+
60+ # Recursive data structures
61+
62+ The record is _recursive_ if it's uses the type of itself in its attribute definition.
63+
64+ ### RecordOrCollection.define({ attributes : { name : `attrDef` } })
65+
66+ Used in conjunction with `@predefine` decorator to make recursive definitions
67+ referencing the same type.
68+
69+ Replaces `static attributes` declaration.
70+
71+ ```javascript
72+ @predefine class Comment extends Record{}
73+
74+ Comment.define({
75+ attributes : {
76+ text : String,
77+ replies : Comment.Collection
78+ }
79+ });
80+ ```
81+
82+ ### Forward collection declaration
83+
84+ As an alternative to `@predefine` decorator, you may make forward declaration for the collection.
85+
86+ ```javascript
87+ // Declare the collection class.
88+ @define class Comments extends Record.Collection {}
89+
90+ @define class Comment extends Record({
91+ static Collection = Comments; // Make it the default Comment collection.
92+
93+ attributes : {
94+ text : String,
95+ replies : Comments
96+ }
97+ });
98+ ```
0 commit comments