Skip to content
This repository has been archived by the owner on Aug 13, 2019. It is now read-only.

How to properly handle interfaces? #6

Open
dradtke opened this issue Jul 30, 2013 · 4 comments
Open

How to properly handle interfaces? #6

dradtke opened this issue Jul 30, 2013 · 4 comments
Labels

Comments

@dradtke
Copy link
Contributor

dradtke commented Jul 30, 2013

In particular I'm interested in implementing the GtkBuildable interface, which is implemented by a crap-ton of things. However, my initial attempt based on existing code to implement it for Widget results in a mess of "ambiguous selector v.GObject" and "too few values in struct initializer" errors.

Thinking about it some more, I'm not sure why it wouldn't be feasible to just create an IBuildable interface implementing toBuildable(), then define that for each object that implements it. Is there a reason that, for example, ComboBox is implemented the way that it is with the CellLayout anonymous field? Is having ICellLayout not enough?

@jrick
Copy link
Member

jrick commented Aug 5, 2013

IBuildable sounds like the right way to go about this. I originally implemented these GInterfaces that way with the anonymous fields because I didn't want to reimplement a million different functions for each interface, which all performed the exact same code, but taking different types as the receiver. Keeping, for example, the CellLayout type as a struct, with all its normal implemented fields, and then adding the go interface ICellLayout to everything which implements sounds like a much better way to go about this. It would also simplify all of the new wrap*() functions.

@dradtke
Copy link
Contributor Author

dradtke commented Aug 5, 2013

Looking at it some more I understand better some of the original decisions, and it might actually be best to stick with the struct and interface model, but update the wrap methods. For example:

type Widget struct {
    glib.InitiallyUnowned
    // Interfaces
    *Buildable
}

type Buildable struct {
    obj *glib.Object
}

type IBuildable interface {
    GetName() string
}

func (b *Buildable) GetName() {
    // sole implementation of gtk_buildable_get_name()
    ...
}

And then the wrap methods could be implemented kind of like

func wrapWidget(obj *glib.Object) *Widget {
    w := new(Widget)
    w.InitiallyUnowned = &glib.InitiallyUnowned{obj}
    w.Buildable = &Buildable{obj}
    return w
}

// example of subclassing Widget
func wrapContainer(obj *glib.Object) *Container {
    c := new(Container)
    c.Widget = *wrapWidget(obj)
    return c
}

This code isn't really tested and so might contain some errors, but it should highlight the approach that I have in mind, which would hopefully prevent duplication of interface functionality.

@jrick
Copy link
Member

jrick commented Aug 5, 2013

Oh I remember why I had chosen to do it that way originally. If some object implements Buildable and provides function GetName(), I want to be able to call obj.GetName() instead of using obj.GetBuildable().GetName(). If Go allowed defining functions with interfaces as receivers, this wouldn't be an issue.

@dradtke
Copy link
Contributor Author

dradtke commented Aug 6, 2013

I came up with an example for a solution in my fork. Basically I added *Buildable as a field to Widget, then updated all of the wrap methods to pass the new struct up to the parent wrap function. This means that Widget and anything that subclasses it will contain all of the methods of Buildable directly. It might need some more tweaking, but it looks like it would work.

andre-hub added a commit to andre-hub/gotk3 that referenced this issue Feb 13, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants