RealmAny
RealmAny
is used to represent a polymorphic Realm value.
At any particular moment an instance of this class stores a definite value of a definite type. If, for instance, that is a Double
value, you may call asDouble to extract that value. You may call type to discover what type of value is currently stored. Calling asDouble
on an instance that does not store a Double
value would raise an IllegalStateException.
RealmAny
behaves like a value type on all the supported types except on Realm objects. It means that Realm will not persist any change to the actual RealmAny
value. If a RealmAny
holds a RealmObject, it just holds the reference to it, not a copy of the object. Because RealmAny
instances are immutable, a new instance is needed to update a RealmAny
attribute.
anObject.realmAnyField = RealmAny.create(42.0)
anObject.realmAnyField = RealmAny.create("Hello")
anObject.realmAnyField = RealmAny.create(MyRealmObject())
It is crucial to understand that the act of extracting a value of a particular type requires definite knowledge about the stored type. Calling a getter method for any particular type that is not the same type as the stored value, results in an exception being thrown.
Our recommendation to handle the RealmAny polymorphism is to write a conditional expression with when
around the RealmAny
type and its inner value class.
val realmAny = anObject.realmAnyField
when (realmAny.type) {
INT -> doSomething(realmAny.asInt()) // or as any other primitive derived from 'Number'
BOOLEAN -> doSomething(realmAny.asBoolean())
STRING -> doSomething(realmAny.asString())
BYTE_ARRAY -> doSomething(realmAny.asByteArray())
REALM_INSTANT -> doSomething(realmAny.asRealmInstant())
FLOAT -> doSomething(realmAny.asFloat())
DOUBLE -> doSomething(realmAny.asDouble())
OBJECT_ID -> doSomething(realmAny.asObjectId())
REALM_UUID -> doSomething(realmAny.asRealmUUID())
REALM_OBJECT -> doSomething(realmAny.asRealmObject<MyRealmObject>())
LIST -> doSomething(realmAny.asList())
DICTIONARY -> doSomething(realmAny.asDictionary())
}
Short, Int, Byte, Char and Long values are converted internally to int64_t
values. One has to be aware of this when comparing RealmAny
values generated from different numeral types, for example:
RealmAny.create(42.toShort()) == RealmAny.create(42.toByte()) // true
RealmAny
cannot store null
values, although RealmAny
properties must be declared nullable:
class Warehouse {
var nonNullableStorage: RealmAny = RealmAny.create("invalid") // This is NOT allowed
var nullableStorage: RealmAny? = RealmAny.create("valid") // Property MUST be nullable
var defaultNullStorage: RealmAny? = null // Property MUST be nullable
}
warehouse.nullableStorage = RealmAny.create(22)
warehouse.nullableStorage = null // Assign null directly to the property
RealmAny
cannot store EmbeddedRealmObjects.
RealmAny
can contain other RealmList and RealmDictionary of RealmAny. This means that you can build nested collections inside a RealmAny
-field.
realmObject.realmAnyField = realmAnyListOf(
// Primitive values can be added in collections
1,
// Lists and dictionaries can contain other nested collection types
realmListOf(
realmListOf(),
realmDictionaryOf()
),
realmDictionaryOf(
"key1" to realmListOf(),
"key2" to realmDictionaryOf())
)
DynamicRealmObjects and DynamicMutableRealmObjects can be used inside RealmAny
with the corresponding create function for DynamicRealmObject
s and with asRealmObject using either DynamicRealmObject
or DynamicMutableRealmObject
as the generic parameter.
RealmAny
values can be sorted. The sorting order used between different RealmAny
types, from lowest to highest, is:
Boolean
Byte/Short/Integer/Long/Float/Double/Decimal128
byte[]/String
Date
ObjectId
UUID
RealmObject
RealmAny
properties can be aggregated. RealmQuery.max and RealmQuery.min produce results based the sorting criteria mentioned above and thus the output type will be a RealmAny
instance containing the corresponding polymorphic value. RealmQuery.sum computes the sum of all numerical values, ignoring other data types, and returns a Decimal128 result - SUM
s cannot be typed-coerced, that is, queries like this are not allowed:
realm.query<Warehouse>()
.sum<Float>("nullableStorage") // type CANNOT be coerced to Float
Types
Properties
Returns the Type of the RealmAny
instance.
Functions
Returns the value from this RealmAny
as a ByteArray.
Returns the value from this RealmAny
as a Decimal128.
Returns the value from this RealmAny
as a RealmDictionary containing new RealmAnys.
Returns the value from this RealmAny
as a BsonObjectId.
Returns the value from this RealmAny
as a RealmInstant.
Returns the value from this RealmAny as a BaseRealmObject of type T.
Creates an unmanaged RealmAny
instance from a BaseRealmObject value.
Returns the value from this RealmAny
as a RealmUUID.