On 2 February 2011 00:10, James Moschou <[email protected]> wrote: > Hello, > > I have an abstract class, which has a named constructor and would like > to be able to create instances of concrete subclasses by passing the > type to a factory method. Specifically: > > abstract class Document : Object { > Document.with_name (string name) { ... } > } > > class TextDocument : Document { > TextDocument.with_name (string name) { ... } > } > > Document get_document_with_name (string name, Type document_type) { > // Something here ... > } > > // Usage > TextDocument text_document = (TextDocument) get_document_with_name > (name, typeof (TextDocument)); > > > I have a feeling such a thing is possible using GObject constructor > properties and the construct block, but I'm not sure how. I've been > avoiding doing object construction the GObject way up until now, and > would prefer to keep doing so if possible as it is simpler to > understand. > > Also this factory method is just for a special case, i.e. the normal > way to create documents is actually using the new keyword. So if I > have to use GObject construction, I would prefer it to be alongside > the normal constructors; is this possible? The documentation I've read > seems to assume it's one or the other. > > Regards, > James >
I think I've managed to solve this in a robust, if a bit convoluted way. It involved delegating the initialisation code out of the constructors to virtual init... methods. Utilising virtual methods is what allows the factory method to work. Then I used the concept of a "designated initialiser" to ensure the classes would chain up in the correct order, without weird behaviour happening with overridden virtual methods. http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/ObjectiveC/Articles/ocAllocInit.html (about half way down) Altogether: abstract class Document : Object { Document () { init (); } Document.with_name (string name) { init_with_name (name); } // init is the designated initaliser virtual void init () { ... } virtual void init_with_name (string name) { init (); ... } } class TextDocument : Document { TextDocument () { base (); } TextDocument.with_name (string name) { base.with_name (); } // init here is also the designated initialiser // so it chains up to the base designated initialiser override void init () { base.init (); } override void init_with_name (string name) { init (); ... } } Document get_document_with_name (string name, Type document_type) { Document doc = (Document) Object.new (document_type); doc.init_with_name (name); return doc; } This way initialisers get called: 1. Document.init () 2. TextDocument.init () 3. TextDocument.init_with_name () whether using Object.new() or normal construction. I know this probably seems like I'm trying to replicate another programming environment's paradigm where it doesn't belong, but I can't use construct properties, because that forces you to store the passed arguments as properties. I might choose to interpret 'name' as a filepath and store the File object, or just process 'name' without storing anything, etc. Regards James _______________________________________________ vala-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/vala-list
