Change request: do not geenrate constructors with object varargs #213

Closed
opened 2025-04-26 14:58:27 +02:00 by MMarco94 · 8 comments
MMarco94 commented 2025-04-26 14:58:27 +02:00 (Migrated from github.com)

Hello, fir of all, thanks for the amazing library!

I'm the author of compose-4-gtk, a library to instantiate the GTK/ADW widgets in the style of Kotlin Compose, for example:

fun main(args: Array<String>) {
    application("my.example.hello-app", args) {
        ApplicationWindow( "Test", onClose = ::exitApplication) {
            Box(orientation = Orientation.VERTICAL) {
                HeaderBar()
                Label("Example", Modifier.margin(20))
                Button("Button") { println("Clicked!") }
            }
        }
    }
}

While upgrading from JavaGI v0.11 to 0.12, I noticed that the new constructors on GObjects that take Object... propertyNamesAndValues cause a lot of confusion for users of my library.

For example, in the example above, importing by mistake org.gnome.gtk.Label won't raise any compilation error, but will crash at runtime, sinceModifier is not a supported property.

In general, the new signatures are very broad, and not type safe.


I have some suggestions:

  • Instead of a constructor, generate an equivalent static function, e.g. Label.fromProperties(Object... propertyNamesAndValues)
  • Since the first parameter of propertyNamesAndValues has to be a string, why not changing the signature to String propertyName, Object... propertyValues? This, plus an empty constructor, should offer the same feature, with a bit more safety.
  • Drop the constructor completely

I think the first suggestion would be the best one. What do you think?

Thanks!

Hello, fir of all, thanks for the amazing library! I'm the author of [compose-4-gtk](https://github.com/MMarco94/compose-4-gtk), a library to instantiate the GTK/ADW widgets in the style of Kotlin Compose, for example: ``` fun main(args: Array<String>) { application("my.example.hello-app", args) { ApplicationWindow( "Test", onClose = ::exitApplication) { Box(orientation = Orientation.VERTICAL) { HeaderBar() Label("Example", Modifier.margin(20)) Button("Button") { println("Clicked!") } } } } } ``` ---- While upgrading from JavaGI `v0.11` to `0.12`, I noticed that the new constructors on GObjects that take `Object... propertyNamesAndValues` cause a lot of confusion for users of my library. For example, in the example above, importing by mistake `org.gnome.gtk.Label` won't raise any compilation error, but will crash at runtime, since`Modifier` is not a supported property. In general, the new signatures are very broad, and not type safe. ---- I have some suggestions: - Instead of a constructor, generate an equivalent static function, e.g. `Label.fromProperties(Object... propertyNamesAndValues)` - Since the first parameter of `propertyNamesAndValues` has to be a string, why not changing the signature to `String propertyName, Object... propertyValues`? This, plus an empty constructor, should offer the same feature, with a bit more safety. - Drop the constructor completely I think the first suggestion would be the best one. What do you think? Thanks!
jwharm commented 2025-04-26 16:30:59 +02:00 (Migrated from github.com)

Thanks for the feedback!
I didn't realize that the varargs constructor would have such negative consequences, but I agree that this is confusing.

The most important consideration for me, is that I want to have a no-argument constructor to make subclassing as easy as possible. If we change the varargs constructor into a static function, the only constructor that will always be left, is the one that takes a MemorySegment.

So I'd prefer to change the String propertyName, Object... propertyValues version into a factory method, and keep the no-args constructor. OK?

Thanks for the feedback! I didn't realize that the varargs constructor would have such negative consequences, but I agree that this is confusing. The most important consideration for me, is that I want to have a no-argument constructor to make subclassing as easy as possible. If we change the varargs constructor into a static function, the only constructor that will always be left, is the one that takes a MemorySegment. So I'd prefer to change the `String propertyName, Object... propertyValues` version into a factory method, and keep the no-args constructor. OK?
MMarco94 commented 2025-04-26 18:28:49 +02:00 (Migrated from github.com)

Thanks, that works!

Thanks, that works!
jwharm commented 2025-04-27 21:31:06 +02:00 (Migrated from github.com)

I think we even work without the factory method. There's already GObject.newInstance(Class<T>, Object... properties) that can be used for exactly this purpose, so I don't see the need for an extra constructor in every class.

PR #215 changes the varargs constructor into a no-args constructor.

I think we even work without the factory method. There's already `GObject.newInstance(Class<T>, Object... properties)` that can be used for exactly this purpose, so I don't see the need for an extra constructor in every class. PR #215 changes the varargs constructor into a no-args constructor.
MMarco94 commented 2025-04-28 22:34:31 +02:00 (Migrated from github.com)

Thanks for making the change :)

Thanks for making the change :)
jwharm commented 2025-04-30 20:53:33 +02:00 (Migrated from github.com)

The fix is in release 0.12.1-RC1. Can you please let me know if it works for you? Thanks in advance.

The fix is in release 0.12.1-RC1. Can you please let me know if it works for you? Thanks in advance.
MMarco94 commented 2025-05-02 12:17:19 +02:00 (Migrated from github.com)

Can I download 0.12.1-RC1 from Maven?
Alternatively, are the generated sources published somewhere?

I tried to generate the sources myself, but I get errors like No GIR files found for Gdk. Do you have a guide on how to set up the project?

Can I download `0.12.1-RC1` from Maven? Alternatively, are the generated sources published somewhere? I tried to generate the sources myself, but I get errors like `No GIR files found for Gdk`. Do you have a guide on how to set up the project?
jwharm commented 2025-05-02 13:11:48 +02:00 (Migrated from github.com)

Yes, the RC version is on Maven Central so you can just change the version of the dependency.

The generated sources aren’t checked into git, but there are sources.jar on Maven Central. To generate them yourself, clone the java-gi repo with the --recurse-submodules option. See the bottom of this page for complete instructions: https://jwharm.github.io/java-gi/generate/

Yes, the RC version is on Maven Central so you can just change the version of the dependency. The generated sources aren’t checked into git, but there are sources.jar on Maven Central. To generate them yourself, clone the java-gi repo with the `--recurse-submodules` option. See the bottom of this page for complete instructions: https://jwharm.github.io/java-gi/generate/
MMarco94 commented 2025-05-02 17:35:43 +02:00 (Migrated from github.com)

Okay, I tried the new version. It works perfectly. Now it's impossible to create a GTK widget by mistake.

Thanks!

Okay, I tried the new version. It works perfectly. Now it's impossible to create a GTK widget by mistake. Thanks!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
java-gi/java-gi#213
No description provided.