Open MJacred opened 1 year ago
now I need to do
value.(interface{}).(string)
to get my string, because string does not implement this interface
This is really weird and probably doesn't work as well as you expect it to, because string
doesn't implement Objector
, so it'll crash right in the function.
Are you sure this isn't a GValue
or something like that?
Are you sure this isn't a
GValue
or something like that?
see EDIT in my description -> it is a GValue (placement was not that good, I guess)
Though the primitives are also valid GValue
s. So it might pose a problem later, if there's a case where the list consists of primitives (haven't found a case, yet)
Closing issue for now?
Yes, though this is one of those scenarios where it's extremely important to defer to the official GTK API documentation:
According to Gtk.FileChooser.get_files, the type of each object in the returned list is a GFile
, not a string! You'll need to do f.CastObject().(gio.Filer)
to get the GFile
in the most correct way possible (there's no guarantee that the returned type is anything concrete, but it must implement the Filer
interface).
Admittedly, the method should be Item(n uint) glib.Objector
, not Item(n uint) *glib.Object
. In fact, since Go has generics now, we can even have a ListStore[Filer]
type. Since the whole package has no stable guarantees at the moment, I might eventually get to changing it to work better.
For now, feel free to close this issue.
Sorry, I should have quoted it directly from my original description (I noticed that it returns *gio.File objects due to the docs and amended it right away):
EDIT: ok, the list model should give *gio.File objects in this case, so no issue here. Though there are probably other cases? if not, this issue can be closed. (code is still untested, as refactoring from gotk3->gotk4 is work in progress)
Admittedly, the method should be Item(n uint) glib.Objector, not Item(n uint) *glib.Object
From what I can see, glib.Objector
is never returned from any method, or taken as parameter (except in the new()
funcs).
The same goes for e.g. gio.ListModeller
.
Isn't that why there's func (v *Object) Cast*() Objector
? At least if you get an object from the API.
But what about the other way around? As these funcs don't take an interface as input, what is the best approach to pass in an object as parameter? glib.BaseObject()
?
Do you intend to change this that the interface shall be taken as input parameter and return value?
From what I can see,
glib.Objector
is never returned from any method, or taken as parameter (except in thenew()
funcs). The same goes for e.g.gio.ListModeller
.
That's definitely weird in hindsight. I tried digging through git blame
and wasn't able to find a reasonable explanation as to why I did that.
Isn't that why there's
func (v *Object) Cast*() Objector
? At least if you get an object from the API.
No Cast()
is implementation detail at best and broken at worst.
Again, it's important to emphasize that the function doesn't necessarily return a *gio.File
, although it may. What it (and the generator) actually does is traversing the type tree:
GDriveFile
type in C.GDriveFile
-> GNetworkFile
(implements GFile
) -> GObject
.A few things to note here:
GObject
implements GFile
, so we can comfortably cast it to any Go type that also implements that interface. *gio.File
type to get the needed methods while still implementing gio.Filer
.*gio.File
at all, so we have to resort to GObject
. This has happened a few times before. Cast()
actually satisfies the returning interface type, since it may not always.FWIW I think it's intentional that the generator generates a ListModel
by itself which just returns a GObject
with no hint as to what the actual type may be (until later on), so there's not much that it can do. Still, returning an Objector
seems to be the better idea here, it'll only add some cost to do type conversion.
Again, it's important to emphasize that the function doesn't necessarily return a
*gio.File
, although it may […]
Ah, yes, indeed. Thanks for the clarification.
After a simple search I found ~80 instances where Objector
should have been returned/taken.
There are similar cases for other types where the interface version should be returned I reckon, such as for func (self *DropDown) Model() *gio.ListModel
.
I guess the affected interfaces need to be identified one by one?
Hmm, in an ideal world, I think we'll generate a type ListModel[T Objector] struct
, but I'm not sure how feasible that actually is. I think maybe making it all return Objector
is good enougn. Yet another special case in the code generator.
Code generators are black magic either way.
Shall I update issue title & description to reflect the issue of "use interface instead of struct for param/return type, if necessary" or close this one and create new issue?
I think this issue is fine as it is.
Ok, then I'll leave title and description as-is and we'll leave the issue open until the struct type is replaced by the interface type
Specs
Problem
what I want to achieve:
EDIT: ok, the list model should give *gio.File objects in this case, so no issue here. Though there are probably other cases? if not, this issue can be closed. (code is still untested, as refactoring from gotk3->gotk4 is work in progress)
problem
Objector
, which is nice-to-have for further casting to specific gtk object, but not to e.g. golang primitive typessteps
Files()
-> returns*gio.ListModel
objectItem(i)
-> retunrs*glib.Object
objectsCastType(glib.TypeString)
-> returnsObjector
value.(interface{}).(string)
to get my string, because string does not implement this interfaceSolution
Cast*()
funcs be changed tointerface{}
? orCast*()
funcs that returninterface{}
? (or sth. along the lines)