Realm-java: Inheritance / Polymorphism

Created on 19 Jan 2015  ·  173Comments  ·  Source: realm/realm-java

A highly request feature is polymorphism. Mostly for use in ListAdapters, but a lot of other scenarios exists.

We need support for the following:

  • Abstract RealmObject classes
  • Query support

Example

public abstract Animal extends RealmObject {
  private String name;
}

public class Dog extends Animal {
  private boolean willPlayCatch;
}

public class Spider extends Animal {
  private boolean isScary;
}

// Following should be possible
RealmResults<Animal> animals = realm.where(Animal.class).equalsTo("name","Foo").findAll();
String name = animals.get(0).getName();

RealmResults<Dog> dogs = realm.where(Dog.class).equalsTo("name","Foo").and().equalsTo("willPlayCatch", true).findAll();
String name = dogs.get(0).getName();
Blocked Design-Required T-Feature

Most helpful comment

Oh come on people, do not just comment "+1", I know my comment also has no point, but, you could all just subscribe to the thread and wait for an actual valid response from someone from the team. This way you're not just flooding the issue with unnecessary entries...

All 173 comments

Any estimate on a time frame for this? I'm hoping to use Realm in an upcoming project, but without support for Model inheritance I'll have to hold off on trying it out.

Looking forward to where you guys take this project though!

Hi @T-Spoon
We have a couple of other major features we would like to look at first, so we don't have a timeframe yet, sorry. If inheritance is a dealbreaker for you, you should probably not use us this time around. But we do hope you will come back :)

:+1:

Still no estimates? Going to write a lot of duplicate code since I want to use Realm anyways. Works fine in swift already. Monitoring this.

Unfortunately not. The support for this in Objective C and Swift is actually just sharing fields. It is not proper polymorphism. This is good enough for some use cases, but we feel that without being able to query on abstract super classes it will be less useful on Android. Right now we are focusing on migrations, null support and async querying, but hopefully we will be able to tackle this afterwards.

@cmelchior So is there any way to share fields on Android? We have 5 models that all share the same synchronization-related fields and code. We use inheritance in our current SQLite models; if we switch to Realm, will we have to duplicate the synchronization fields across each of the 5 model classes?

As a workaround, I'm thinking about having those classes implement an interface with getters and setters for the shared fields, which at least let me share the synchronization code... is there a better way?

While waiting for this inheritance feature to be available, is there any workaround, like a good practice to design our RLMObjects and model to make such use cases possible?

My need is with a typical object model having, say, Animals objets, subclassed as Dogs and Cats, and I want sometimes to fetch all the Animals (to display in a List only common properties of those animals like their name), and sometimes (e.g. when I tap on an item in the list to show the details) to access properties of the specific class Dog or Cat.

Given that I can't use inheritance to represent that in Realm yet, how would you guys represent your data model instead to make this use-case possible? Adding a relationship from the Dog and Cat RLMObjects to the Animal RLMObject (composition instead of inheritance) maybe?

The current solution is to use composition instead of inheritance.
There are lots of good argument about it (Gang of Four and Joshua Bloch to mention some prestigious supporters of this approach).

On the other hand we are considering to allow inheritance, but it would not allow queries.
For example: Animal which is extended both by Dog, Cat and Duck. You would not be able to query Animals with for legs and have all Dogs and Cats, but not Ducks. We feel this would be a very crippling behavior but are eager to listen to more opinions.

@emanuelez Is @AliSoftware's composition-over-inheritance example what you have in mind?

See other model: Im have base object

public abstract class BaseObject {
    private String guid;

    private Map<String, String> name;

    private List<String> tags;

    private double latitude;

    private double longitude;

    private LatLng position;

    @Nullable
    public String getName(String locale) {
        if (name != null) {
            return name.get(locale);
        }
        return null;
    }

    public String getName() {
        return getName(getDefaultLocale());
    }

}

and some other child

public class City extends BaseObject {

    int version;

    boolean current = false;
}
public class Station extends BaseObject {

    Map<String, String> next;

    List<String> routes;

    private List<String> bus;
    private List<String> shuttle;
    private List<String> tram;
    private List<String> troll;
}
public class RoutePoint extends BaseObject {
    int direction;
    String routeGuid;
}

and few other
BaseObject contains also equals and hashCode methods
How much do I need to copy paste the code and how much it will generate errors?

Hi, is there any update about this issue?

Hi @StErMi We are currently focusing on finishing other features, and we cannot move forward with this until we made changes to the underlying storage engine as it must support querying across abstract types. At this time I am afraid I don't have any timeline.

@cmelchior, I can help you guys building this feature but I need little help from you guys in order to get starting so if you can guide me with the kick off process that would be great.

I appreciate your hard work on this excellent piece of software but it's a big pain in the ass not being able to use inheritance as we do in swift. I have a big model in swift full of inheritance that I have to implement in Android and now I realize this is not allowed...I never imagined such a restriction could exist on a object oriented language component.

IMO this is a very important thing but this ticket was opened for almost a year without any estimated timeline so I assume the solution is not near :)

Unfortunately we don't have a timeline yet. We have a long list of features we would like to do, and we are continuously evaluating the order we do them in, so feedback such as yours is much appreciated.

Note that Swift offers inheritance but not polymorphism, which we think would be the expectation for any Java developer for this feature. So for now we recommend using composition instead of inheritance.

@srikalyan Sorry for the late reply. Thank you for your offer, but this feature unfortunately require changes to the underlying core engine (all issues marked "waiting-for-core" does that), but if you find any issues without that label, we would love to start a discussion on them if you want to help.

@cmelchior Just echoing the desire to have polymorphic relationships supported in Realm. Also, some polymorphic solutions seem to be Integer focused; it would be good to have something that supports Binary and String/Hex as well.

Until Realm releases polymorphic support, we're building workarounds at the cost of performance, code efficiency, and model simplicity.

IMO this is a very important thing but this ticket was opened for almost a year without any estimated timeline so I assume the solution is not near :)

I've used Realm for quite a few projects. And having inheritance would save me a lot of trouble. Like someone said before, this ticket was opened a year ago. Realm is my fav library out their for database related stuff in Android. And I hope this feature will be added soon, I think Realm could be a big player in how DB related things get handled in Android. It is great as it is, but missing inheritance in a OOPL like java I think it is a major let down for a lot of people.

I assume there is still no estimated timeline?

Keep up the good work though!

:+1:

+1

+1 Hopefully this feature is still on the table

+1000

+1! :)

+1 plz

+1

+1

+1

+1

+1

+1

Yeah, we're all waiting! Its a very cool DB and we all want INHERITANCE! :D

@emanuelez and @cmelchior I think this proposed approach is acceptable, since the main drawback of not having this is having to repeat a lot of code for objects that share the same behavior. It should be noted on queries that we can't query objects based on a common ancestor, but we should be able to make joint queries (Like: find Dog and Cat where color is black)... On the future, if the demand for ancestor querying grows, then we can think on some way to create a relation between the parent object and it's siblings to allow the query mentioned by Emanuele...

+1 wait for

+1 waiting...

+1

+1

+1

Tracking

+1

+1

+1

One year passed away

@cmelchior It's been a year and more, still have NO answer for this?

Wauu - yeah time flies quickly. We would really love to tackle this very soon. During the past year we have closed about 900 issues. This hasn't been one of them since we have always prioritized supporting/helping developers and fixing bugs as 1. priority. Besides that our priority is to fix things that doesn't have any workarounds. We have also gone completely transparent with our issue mgmt and priorities, and you can see a more detailed priority list if you view the issues in waffle.io.
Our "S:P1 backlog" list will be tackled first and we will make a 1.0 release. After that we expect this to be among the top 3 features to support. This doesn't give you a date, but we really can't predict it - it depends on the future support load. But I hope it gives at least some insight into what we are thinking.

Oh come on people, do not just comment "+1", I know my comment also has no point, but, you could all just subscribe to the thread and wait for an actual valid response from someone from the team. This way you're not just flooding the issue with unnecessary entries...

that was the most simple way to show that we are all waiting for this feature.

Comments from #2643 RealmObject should also be able to extend other non-RealmObject/abstract object.

Hi there. Do you know when we will be able to extend a class that extends RealmObject or implements RealmModel?

Hi, I want to try composition over inheritance for now. Let's say we do what @emanuelez suggested :

class Animal {
int numberOfLegs 
String name
}

and

class Dog  { 
Int furSize
Animal animal
}
class Duck  { 
Int featherSize
Animal animal
}

Now if I query for all Animal.class, I will get all of them (that is awesome btw) BUT, for a given Animal, I can't get the related Dog or Duck (at least i don't know how !).
Do you have any suggestion @emanuelez ?

I though about doing something like query all child class like Dog, Duck, and group them in a list of the same interface (AnimalInterface for example), that would return common data like title, etc... all instead of querying animal.

@NitroG42 If you add a unique id field to the animal class, then you can query for it for all you dogs and ducks. For a cleaner approach you will have to wait for backlinks (https://github.com/realm/realm-java/issues/607)

+1

We've tried composition, but introduced way more problems. Now, instead of developing, we're lots of time hacking the models to fit our bussiness rules. Mangle it with retrofit, deserializers, and all hell broke loose!

This is super painful, I cannot forgive myself for making a huge assumption that Realm supports inheritance. I have a project with a fast-approaching deadline and I had ripped out the good old SQLite/ContentProvider combo and implemented Realm for faster performance and now I hit the wall with Inheritance and composition is not an option for me. I will keep tuned in for this feature.

Overall, I am very happy with all that Realm has offered and I wish the team luck with finding a solution for this.

I'm trying to use Realm and I just ran into this limitation. Is there a timeline for support objects that already have their own inheritance? Composition is not an option for us right now. Is there a timeline for this yet?

+1 - I vote for it. More then a year has passed.
BTW it's a middle of 2016!

I had just started migrating from ActiveAndroid to realm and realised that subclassing is still not supported. I think I will have to go back to looking for another ORM.

I also switched back to SQLite for now as I need to work with database from Service and Activity code.
I found it hard to use realm in such 'multi-threaded' environment.

I can recommend DbFlow, which supports polymorphism

@bryant1410 Had a quick look at DbFlow. I did not like the code it auto-generates. This is totally a personal preference though. why you think DbFlow is better than something like ActiveAndroid?

Do you mean that you don't like its API? Or the code itself? If you don't like the auto-generated code, this is not a problem as you don't have to read it very often (if at all).

In my opinion the game-changing factor here is the performance. ActiveAndroid relies heavily on reflection, while DBFlow uses annotation processing in order to generate classes and to avoid using reflection as little as possible. Reflection is usually slow in Java, and not using it has a big impact. You can take a look to DBFlow's company benchmark about this.

+1 - If you could find a solution for the inheritance to work, that would be awesome!
:)

I have used Realm for quite a while but lack of support of this fundamental OOP characteristic is quite disappointing, a year and a half is quite a long time to have built the required support.

Just ran into this problem. It would be very great if this feature gets prioritized. Gonna have to abandon Realm for now and use other ones. Updates from devs would definitely be appreciated!

This issue means I can't attach any JSONAPI deserializers like moshi-jsonapi in Android (which requires that you extend your class with Resource, which means you can't extend RealmObject or vice versa. Anybody have a temporary workaround for something like this?

@lordplagus02 See https://realm.io/docs/java/latest/#realmmodel-interface

I think you've just saved my day, what with deadlines fast approaching and solutions undiscovered... you know how it is

@beeender It appears that it still doesn't actually help, you still can't extend or implement anything that isn't Realm related...

@lordplagus02 Sorry I missed that part "moshi-jsonapi in Android (which requires that you extend your class with Resource" ... I think for now you need to find some other ways if you want to use moshi-jsonapi and Realm together, maybe create some delegate class? Not sure if there is an easy way to do it.

@beeender easiest way was to revert to moshi-jsonapi v1.x because it doesn't require that you extend Resource. I think due to the current limitations of Realm, we're still awhile away from a full jsonapi/realm/syncadapter implementation.

Looking at it, a possibility is forking the project and rewriting it to use interface instead of hard-coding their abstract class

+1

Hello,

I'm trying to reshape my code and models to workaround this issue through composition.

enum ChildType {
    CAT, DOG
}

class Animal extends RealmObject implements CatInterface, DogInterface {

    @PrimaryKey
    @Required
    private String id;

    @Ignore
    private ChildType type;
    private String typeDescription;

    private ChildMarker child;

    public Animal() {
    }

    public Animal(ChildMarker childMarker) {
        if (childMarker instanceof Cat) {
            type = ChildType.CAT;
        } else if (childMarker instanceof Dog) {
            type = ChildType.DOG;
        }
    }

    public ChildType getType() {
        if (type == null) {
            type = ChildType.valueOf(typeDescription);
        }
        return type;
    }

    public void setType(ChildType type) {
        this.type = type;
        this.typeDescription = type.name();
    }

    @Override
    public Object getCatAttribute() {
        if (type != ChildType.CAT) {
            return null;
        }
        return ((Cat) child).getCatAttribute();
    }

    @Override
    public void setCatAttribute(Object catAttribute) {
        if (type != ChildType.CAT) {
            return;
        }
        ((Cat) child).setCatAttribute(catAttribute);
    }


}

interface ChildMarker {
}

interface CatInterface extends ChildMarker {
    Object getCatAttribute();

    void setCatAttribute(Object catAttribute);
}

class Cat extends RealmObject implements CatInterface {

    private Object catAttribute;

    @Override
    public Object getCatAttribute() {
        return catAttribute;
    }

    @Override
    public void setCatAttribute(Object catAttribute) {
        this.catAttribute = catAttribute;
    }
}

interface DogInterface extends ChildMarker {

}

class Dog extends RealmObject implements DogInterface {

}

But my ChildMarker is not supported, Does it mean I have to have one attribute of each child type in my Animal class ? I could also do my composition the other way around, with children containig their mother. But I'd like only one table, I don't know in advance if I'm looking for a dog or a cat and since reverse lookup is in development (#607) I'll have to wait for it.

It would be great if we could have a working code alternative in this topic

enum ChildType {
    CAT, DOG
}

class Animal extends RealmObject implements CatInterface, DogInterface {
    // animal attributes
    @PrimaryKey
    @Required
    private String id;

    @Required
    @Index
    private String type;

    public String getType() {
         return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setChildType(ChildType childType) {
        setType(childType.name());
    }

    public ChildType getChildType() {
        return ChildType.valueOf(this.type);
    }

    public Animal() {
    }

    // cat attributes
    private String catSomething;
        // getter, setter

    // dog attributes
    private String dogSomething;
        // getter, setter
}

interface AnimalInterface {
    //animal's fields' getters/setters
}

interface CatInterface extends AnimalInterface {
    String getCatSomething();

    void setCatSomething(String catSomething);
}

interface DogInterface extends AnimalInterface  {
    String getDogSomething();

    void setDogSomething(String dogSomething);
}

Then

    RealmResults<CatInterface> cats = 
                         (RealmResults<CatInterface>)((RealmResults)(realm.where(Animal.class)
                                                         .equalTo(AnimalFields.TYPE, ChildType.CAT.name())
                                                         .findAll()));

But the interfaces aren't necessary if you can afford to keep it as Animal.

@Zhuinden Nice ! thanks it looks like what I did but better

Can I bump this? Any update on this feature?

I was just modifying my Realm classes to work with Polymorphism but then I faced this issue ):

I wanted to make General functions to work with my "BaseObject (which extends RealmObject)" so I could use them with any Child classs.

Only interfaces are supported at the moment, base classes other than RealmObject are not.

I assumed that inheritance is here by default and refactored my code around it without compiling in the process (yes, I am naive but if the support won't be added I am gonna have to have lots of code duplications around primary keys for each model, what the point of using Realm then?)
Waiting for an update

@bogomazov

I am gonna have to have lots of code duplications around primary keys for each model

you can always use an interface, and a repository implementation for T extends YourInterface.

That's what I did, but it causes for quite a bit of un-dry code in your object classes. The interface is just useful for your getters and setters at the end of the day. It desperately needs some polymorphism.
On 4 Nov 2016 12:18 am, Gabor Varadi [email protected] wrote:

@bogomazov you can always use an interface, and a repository implementation for T extends YourInterface.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@lordplagus02 and @bogomazov can you show me an example of the Repository implementation that you got working for you. I am using Repository implementation, maybe I am doing it wrong.

My model class was simple, a LineItem that inherits from a Product like so:

public class LineItem extends Product {
    private long id;
    private int quantity;

    public LineItem(Product product, int quantity) {
        super(product);
        this.quantity = quantity;        
    }
}

I have now changed this to this as a work around.

@RealmClass
public class LineItem implements RealmModel {
    private long id;
    private int quantity;
    private long productId;
    private Product product;

    public LineItem() {
    }

    public LineItem(Product product, int quantity) {
        this.quantity = quantity;
        this.productId = product.getId();
        this.product = product;
    }
}

Here is my repository interface, how can I change my repository implementation to support polymorphism.

 public interface Repository{
        List<LineItem> getAllLineItemsInATransaction(long transactionId);
        long saveLineItem(LineItem lineItem);
        void updateLineItem(LineItem lineItem);
        LineItem getLineItemById(long id);
        void deleteLineItem(long id);
    }

I do not see a single place where you're actually sharing fields with Product.

LineItem is inheriting from Product and then adding properties that are LineItem specific such as quantity, discount, refund, etc. I have not shown those for brevity. The goal is not to duplicate the properties of Product such as name, image, price, etc again in LineItem hence the inheritance.

+1

sigh this is messing with my zen

Wow 2 years

it is a complicated problem, and using common interfaces is a fairly simple workaround

Can someone help with this? http://stackoverflow.com/questions/42259735/composition-over-inheritance-for-realmobjects-with-gson-serialization

I'm totally stuck. This is incredibly frustrating and no one seems to have posted a thorough example of how to work around this issue, and if I can't figure out a workaround, then Realm isn't even an option. I'm astonished they haven't addressed inheritance in two years; I get that development takes time, but inheritance is one of the basic principles of OOP. How can anyone use this if their app has even a modicum of complexity?

You should map your JSON responses into a Realm schema. Don't just directly map GSON's classes into Realm, it's generally a bad idea to assume that your API calls and your database will 1-to-1 match each other directly.

I've made apps that had different types of data and the like, you just need to copy the properties and share a common interface. Frustrating in a sense, inheriting fields is simpler ; but that's just how it is.

Why don't you state clearly in RealmModel interface that class implementing it cannot extend any class? Documentation in current form leads to opposite conclusion.

I really do think the fact that you can't inherit from a class that only has @Ignore'd fields or no fields at all is a bug.

@Zhuinden But if an object only has @Ignore fields or no fields, what is the point of being a RealmObject?

@beeender example code

public class BaseObservable implements Observable {
    @Ignore
    private transient PropertyChangeRegistry mCallbacks;

    @Override
    public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
        if (mCallbacks == null) {
            mCallbacks = new PropertyChangeRegistry();
        }
        mCallbacks.add(callback);
    }

    @Override
    public synchronized void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
        if (mCallbacks != null) {
            mCallbacks.remove(callback);
        }
    }

    @Override
    public synchronized void notifyChange() {
        if (mCallbacks != null) {
            mCallbacks.notifyCallbacks(this, 0, null);
        }
    }

    public void notifyPropertyChanged(int fieldId) {
        if (mCallbacks != null) {
            mCallbacks.notifyCallbacks(this, fieldId, null);
        }
    }
}

@RealmClass
public class ObservableDog extends BaseObservable implements RealmModel {
    @PrimaryKey
    private long id;

    private String text;

    @Bindable
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
        if(!isManaged()) {
            notifyPropertyChanged(BR.id);
        }
    }

    @Bindable
    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
        if(!isManaged()) {
            notifyPropertyChanged(BR.text);
        }
    }
}

This code fails on the Realm annotation processor, even though parent is not a RealmObject and it does not have any inherited fields that Realm could "use"

any update on this issue ?

Any update on this issue?

I have models that look like this:

class Chat extends RealmObject {
    RealmList<TextMessage> textMessages;
    RealmList<ImageMessage> imageMessages;
}
class Message extends RealmObject {
    //some common fields
}
class TextMessage extends RealmObject {
    Message baseMessage;
}
class ImageMessage extends RealmObject {
    Message baseMessage;
}

instead of looking something like this:

class Chat extends RealmObject {
    RealmList<Message> messages
}
class Message extends RealmObject {
    //some common fields
}
class TextMessage extends Message {}
class ImageMessage extends Message {}

and it's a nightmare to add more message types or even write queries.

I do not see why you have any more realmObjects beyond Message

@Zhuinden Because I have more fields in TextMessage and ImageMessage, which I haven't included here for the sake of readability.

@VedavyasBhat I stand by my question. It would have been easier to just include nullable fields and a @Index String type field.

@Zhuinden: I see what you have in mind, but I have the same issue as @VedavyasBhat: I want to be able to attach Actions and Observations to an object, both being an event in time with some shared attributes. But since both have >10 unique attributes I would end up with a large class Event which I consider hard to maintain.

Also I am afraid that I will loose productivity when using code completion and that it will add a source for errors (accessing fields from the wrong type, ...).

But it is a feasible workaround, factory methods will help constructing the right type.

When I had this, I prefixed the fields with what event type (in my case, post type) the given field belonged to.

  1. What is the problem in this code? I tried to follow above code.
    but,
    Error:(11, 8) error: Realm model classes must either extend RealmObject or implement RealmModel to be considered a valid model class

Component.java

public abstract class Component extends RealmObject {

    private String name;

    public Component(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Card.java

public class Card extends Component {
    public Card(String name) {
        super(name);
    }
}

Folder.java

public class Folder extends Component {
    private RealmList<Component> list = new RealmList<Component>();

    public Folder(String name) {
        super(name);
    }

    public Folder add(Component item) {
        list.add(item);
        return this;
    }

    public RealmList<Component> getList() {
        return list;
    }
}
  1. is there something solution??

The only "direct base class" a RealmObject can extend is extends RealmObject.

Anything else must be done through interface.

If I want to make the class through realm, I must have to extends RealmObject. Right??

So then,

public class Card extends RealmObject implements Cardable {
    ...
}

public class Folder extends RealmObject implement Folderable {
...
}

Right??

And I have a question. is it impossible above example code?? (Animal, Dog, Spider and getting RealmResult through Animal etc)

@Heepie to obtain all those types of animals as Animal, currently you'd need

public class Animal extends RealmObject {
    @PrimaryKey
    private String animalId;

    private String dogName;
    private String spiderPoison;
    /// ...

    @Index
    private String animalType; // DOG, SPIDER, ...

Basically a single RealmObject class that merges the types together and its type is determined by a discriminator column (Single Table Inheritance).

@Zhuinden Think you so much :)

I'll try Single Table Inheritance!

I started with implementing Realm in my project and hit this roadblock on the very first insert:| Do you guys have any eta on this yet?

@anuragopenxcell realm-core started some experimental work on this feature, but this still has a low priority for us. We cannot give a estimation on it. sorry.

@beeender to bad that is has such a low priority as it's the most wanted feature / issue here


image

Single-Table inheritance still works. If you design the schema taking the constraints of RealmModels in consideration, everything still works just fine. Especially considering you can mimic the behavior with interfaces if you intend to go so far.

This issue blocks #166 - Added Realm extensions to FlexibleAdapter.
Any estimate on doing this?

@omidraha they didn't say blocked, just inconvenient. (having to implement IFlexible on each RealmObject)

Should be nice to have this feature working, and looks like a lot of people are waiting/needing it for more than 2 years. There is any way to increase the priority?

@YamilMarques probably after some other essential features that are on the way such as cascade deletes and list of primitives

Thanks for the update @zhuinden. I've been using realm without the polymorphism feature but wish it had it especially at the beginning of our project.

While all three of these features are very important, now I think list of primitives should be a step higher priority than polymorphism.

Thereafter, the error message should be more clear:

Error:(9, 8) error: Valid model classes must either extend RealmObject or implement RealmModel.

I did implement RealmModel, however I extended another class too. I assumed polymorphism would be supported and the error message doesn't state otherwise.

Any news ?

Time flies, it's been 2 years, still no news?

Well a bunch of other things were added and are on the table

I`m really interested in this and it would be awesome to have it.

Backlog label removed. Does that mean it's being worked on? Please say yes 😄

We have begun some preliminary work yes (don't hold your breath though, we want to finish #575 first), but it is mostly because we switched to Zenhub to do issue management which has its own way of tracking it instead of GitHub labels.

+1

+1

+1

If you guys fix issues 761 and 575, I will actually start using it on my projects again. I stopped using Realm because of the limitations these unfinished tickets imposed on architecture. These changes would be incredible.

@markiantorno well, #575 is in the works (although I think the "SQLite approach" of storing the primitive list as a single String field, then transform it to List in the getter worked wonders), in the meantime the single-table inheritance approach works well, although I do admit having to do that yourself imposes limitation on how you'd normally portray your object hierarchy.

@Zhuinden ...especially when you're trying to build support libraries for pre-existing tools with really deep hierarchies (like http://hl7.org/fhir/ for example). Don't get me wrong, I love Realm and think it's fantastic. It just needs these two features for me to really integrate it into the software I'm writing at the hospital.

Please update the docs and mention that it's not possible: https://realm.io/docs/java/latest/#customizing-objects

Please make it possible. It is possible in Swift, why not Java? Would be a nightmare to re-design the logic. If I had known this, I would not choose Realm.

Are we going to have this functionality any time soon ? Any updates ?

Yeah also wanting this feature

It's not possible to use DataBinding Android feature without this issue or we duplicate all realmClass for wrap in BaseObservable class. Please add this in future version.

@komuros actually, BaseObservable is a convenience class, although you do need to duplicate that across the RealmObjects to make it work.

See https://medium.com/@Zhuinden/realm-1-2-0-android-data-binding-1dc06822287f

@cmelchior welp, hopefully once the Realm Cloud is up and running, hopefully the Core team will be able to focus on this kind of stuff - ObjectBox 1.4 seems to have introduced entity inheritance: http://objectbox.io/objectbox-1-4-property-queries-entity-inheritance/

Any updates on this task?

Any updates on this task?

Once in a while,
Just get a promising email with this title of the issue,
And then see nothing, just one message left to request it.

When? 😐

They should at least say something about it here, like "we're working on it" or "we're not working on it".

It's Thursday morning,
Github emails an alert,
Maybe Realm is fixed?

I am Mark's sense of disappointment.

Maybe Realm is fixed?

It's not broken :stuck_out_tongue:

Anyways, if people want to bang some walls, they should do it on the following Realm-Core issues instead:

https://github.com/realm/realm-core/issues/778

and

https://github.com/realm/realm-core/issues/946

It's pretty broken without this... I have been continuing to use realm on my projects for some time in the hopes that this would be a priority and would have been added by now. IOS has had it for some time. Any ideas on when this might be implemented? Or if it will ever be implemented? It's causing my projects to be unnecessarily dirty and I would like to find an alternative to Realm if this is not going to be implemented anytime soon.

I, too, was waiting for them to add this functionality for a long time. But as it's not been added, I have started using Room with LiveData. It would have been very nice if only realm had this implemented.

@noshaf @missverma Sorry for not addressing this sooner. Our highest priority has lately been to add synchronisation capabilities as that adds a whole lot of value and solves a major pain point for many apps and developers.

From an Android perspective, the thinking was that we wanted to do it properly and hence has been waiting for a proper solution in core. In contrast we have had some support for this for iOS with some limitations. What we are likely going to do in a "not too distant future" is to make the same support in Android, so we can at least solve some of the use cases, instead of waiting for the perfect solution. It's unfortunately not possible for me to be more precise about when we can get to it, but we are very soon going to plan it out.

In the meantime, if anyone is interested it would be possible to help contribute this feature at the same level as iOS has it :-)

Thanks for the patience!

Polymorphism is not supported in Swift either.

Personally, I think primitive list queries are more interesting than this; while it's not pretty, you can at least use single-table-inheritance without too much hacks.

Also, Kotlin lets you do

interface Category {
    var name: String?
}

so you don't need to inherit getters/setters. This lets you share fields via common interface, but it of course still doesn't allow querying between tables.

I'm not familiar with what Realm iOS provides, but our needs are similar to what is mentioned in the OP. We're less interested in being able to share fields (although that would also be helpful) and more interested in being able to store a heterogeneous list of objects with the same base class (or interface). For example, with the classes defined in the OP, we might also have:

public class Person extends RealmObject {
  private RealmList<Animal> pets;
}

This doesn't seem necessary in the above example, but for our use case the order of the objects in the list matters, which is why we can't just split up our data into multiple concrete lists.

@bmunkholm I assume that the "proper solution in core" is the only way to do this?

My understanding is that the only way to do this currently is to use a wrapper object, such as:

public class AnimalWrapper extends RealmObject {
  // Only one of the following fields can be non-null
  private Dog dog;
  private Spider spider;

  public Animal getAnimal() {
    // return non-null animal
  }
}

public class Person extends RealmObject {
  private RealmList<AnimalWrapper> pets;
}

Where Animal is an interface that Dog and Spider implement.

We're less interested in being able to share fields (although that would also be helpful) and more interested in being able to store a heterogeneous list of objects with the same base class (or interface).

That isn't supported by iOS either at this time.


The only way to have "heterogenous collections" at this time is if you use the same class to model all child classes.

Have a field like

private String type;

which specifies which child class it is.

public class Animal extends RealmObject {
    @Index
    private String type;

    // possibly not-null only if `type == "SPIDER"`
    private String spiderProperty;
    private String spiderOtherProperty;

    // possibly not-null only if `type == "DOG"`
    private String dogProperty;
    private String dogOtherProperty;
    private String dogAnotherProperty;
}

That would allow storing items of different type. This is technically what is called single-table inheritance, and relational databases tend to use the same approach, except the ORM in-between allows the "syntactic sugar" of mapping them to different classes (child classes).

The only way to have "heterogenous collections" at this time is if you use the same class to model all child classes.

What about the object wrapper example I gave? I agree that it's not ideal, but this would still allow for model objects (and any logic) to be separated, rather than creating one giant model. Granted, it wouldn't allow for shared fields, but you could potentially get around that with some Kotlin trickery like you mentioned above. Still, I want proper inheritance.

My main point was just to say that on the surface, it doesn't sound like the limited support that @bmunkholm mentioned in the "not too distant future" would meet our needs. However, I'd like to hear more about what exactly that is (as I said, I'm not familiar with what Realm iOS does support).

Another user in the list waiting...

Guys, just answer us! Are you working on this problem or are we already diverge? :older_man:

We're back on Room now. It works well and integrates no problem with the existing Android tools. I suggest everyone do the same.

@markiantorno I did not know anything about the Room. Does it have the same advantages as Realm?

@SergeyAppDroid

It's basically a wrapper around SQLlite. However, it's built and maintained by Google, and a lot of the new Android Architecture components play very well with it. You'll also notice that the examples provided by Google on their site, all use Room. So if you are learning Android development, or referring to the existing documentation, it helps a lot.

Take a look here:
https://www.youtube.com/watch?v=SKWh4ckvFPM

https://developer.android.com/topic/libraries/architecture/room
https://developer.android.com/training/data-storage/room/defining-data

It's easy to set up and learn. Give it a try.

@markiantorno I'm a little upset that in the Room you need to use SQL. And is there any support for List Objects? (how can Realm)

@SergeyAppDroid @markiantorno Let's not pollute this issue with discussions about alternatives to Realm, we can have a pro/con discussion elsewhere :-), but let's stick to the issue here. Thanks!

This issue is certainly one that we intend to solve and although I really can't tell exactly when, I can promise that it won't take another year. I'm personally hoping for it as an xmas present.

Personally I'm more hyped for primitive list queries.

But field sharing is nice too, technically if you can do it with a single table and discriminator fields by hand, then it ought to be possible in general. Although not a simple problem.

I would personally be happy with at least getting shared fields. All of our models have the same set of minimal fields (timestamp, created date, etc), and having to duplicate those fields, and the associated functionality, in every model is extremely cumbersome. Is there some other way to accomplish this currently in Realm that I am missing, or are we left to wait for some form of inheritance?

hours of implementation and realm punch in the face 😭

Is there some other way to accomplish this currently in Realm that I am missing, or are we left to wait for some form of inheritance?

Simple way is to use Kotlin and your interfaces can define a var field and that works just fine 😄


@hailhate the problem with your approach is that now you must manually delete cascade

Simple way is to use Kotlin and your interfaces can define a var field and that works just fine 😄

Another issue would be querying for the interface instead of the actual class. Is this possible?

E.g. I have an interface A with classes implementing it B and C.
Is it possible to "get all A"? Currently, I need to query for "all B" and "all C" and merge the result (casting to A).

Okay, no, if that's what you need then the only thing you can do atm is you emulating polymorphism via single-table-inheritance-with-discriminator-field.

Meaning you have 1 big RealmObject that can possibly contain all fields of all "inheriting" objects and you also have a field called something like type or objectType or whatever which is most likely a String that is indexed and then you can query the data of a given type based on that

As a result, the problem will be solved? This is the main problem of realm. It makes use of it completely.

I can give you a list of at least 3 things that are more important than this, considering for this you at least have a workaround at your disposal.

@Zhuinden, Good idea,
Please publish roadmap list of realm, So we know where the priority of this issue is located.

Don't look at me, I don't work for Realm and I can't see their priority list either :smile:

To give a brief update:

  • we are working on a improvement of the core DB structure (called Core6) that is a pre-cursor to enable inheritance / Polyphormism (and other features such as Cascading Deletes etc).
  • this work is actually now accelerated post-MongoDB acquisition (which is good news).
  • once that is in place then we will tackle the features/capabilities that have a dependency on this Core 6 improvement.
  • we heard you: we are actively working on it.
  • it will (still) take us months (though not years) to do it

@roberhofer
Polyphormism is definitely an improvement for devs.
Cascading Delete, is the biggest issue, we have been struggling with it. Users are impacted with Orphan children in DB for ever.

Do you have any priority on these?

I'm waiting too... In my project I have a lot duplicate classes I need Inheritance...

I am also eagerly waiting for this feature.

I'm also ))

Is there any update on this?

You can check the road map where it is mentioned that it will happen one day.

(I am not a member of Realm)

Was this page helpful?
0 / 5 - 0 ratings