Repository navigation
Java 8 Interface Binding #25
Description
Activity
At present, I'm leaning toward (2) Expose Them, if only because it's implementation is simple (though the documentation effort regarding the presence of
HelloJava8.InvokeDefaultMethod()isn't simple).I don't think ignoring them is an option.
I don't like (2) Expose Them. It adds unneeded name mangling. The documentation issue is also a major challenge.
I like (3) Treat them specially, It feels much cleaner from a consumer perspective.Reacted by Jason Rai, NickAc and Przemysław RaciborskiI don't like (2) Expose Them. It adds unneeded name mangling.
I don't understand what you mean by "unneeded name mangling." What name mangling? The
Invokehelpers?The documentation issue is also a major challenge.
Agreed. However, (3) also has documentation issues, just different documentation issues.
Yes, the
Invokehelper. Mangling might not have been the right language there.What documentation do you think will be needed? I can understand that (2)
InvokeRequiring docsWhat documentation do you think will be needed [in (3)]?
The presence and use of the
IDefaultMethodsinterface. It'll be a situation of "Java declares aHelloJava8.defaultMethod()interface method, and I can call that method from C#, but how do I implement that method in C#? It's not present in theIHelloJava8interface." It's in theHelloJava8.IDefaultMethodsinterface, which code completion won't know about, and who's going to know to look for that interface without...documentation. :-)(2) answers that question: it's an interface method, therefore you implement it. It's only when you don't want to implement the default interface method that documentation is required, or when you want to invoke the default behavior.
Both (2) and (3) raise the question of what to do with our "missing abstract method generator" (@radekdoulik? ;-) -- presumably it should check for and use the default interface method if present, but we'd need a way for the generator to know that (likely a new custom attribute).
- added a commit that references this issue
on May 25, 2016 Ignore them and Treat them specially don't interact well with Java versioning:
defaultinterface methods aren't restricted to new methods; existing methods can be madedefault!Case in point: [
java.lang.reflect.AnnotatedElement.html.isAnnotationPresent()](https://developer.android.com/reference/java/lang/reflect/AnnotatedElement.html#isAnnotationPresent%28java.lang.Class<? extends java.lang.annotation.Annotation>%29) is non-defaultin API-23 and is nowdefaultin API-24. The Ignore them and Treat them specially approaches result in removing theIsAnnotationPresent()method from theIAnnotatedElementinterface, which would break all implementations.This can be fixed in
Mono.Android.dll-- we know what the previous API is, we can manually fixup such removed members -- but I'm dubious of the effects on 3rd party.jarbindings such as the Android Support library. I believe that most.jarbindings will consist of as little effort as possible to get a compiling binding, and if the.jarchanges interface methods to default interface methods between versions, this can break existing C# interface implementations.I'm very dubious of solutions (1) and (3) right now.
The Expose them (2) approach has a different problem: if
defaultmethods are added to an interface over time, that means that previously built C# classes implementing the interface will break.Xamarin.Android 6.1 added some support to "fixup" added interface methods with an implementation that throws
AbstractMethodError, which made sense then, but doesn't make sense in the context of default interface methods.What we can instead do is place a custom attribute on the default method which refers to the class with the
Invokemethod wrapper:public interface IHelloJava8 { public void A (); [JavaDefaultInterfaceMethod (typeof (HelloJava8))] public void DefaultMethod (); } partial public class HelloJava8 { public void InvokeDefaultMethod(IHelloJava8 self) {...} }The abstract method fixup code could then fixup "missing" interface methods to invoke the default method:
/* IHelloJava8 vPrev lacks defaultMethod(), for arguments sake */ class MyHello : IHelloJava8 { public void A () {} // NO implementation of DefaultMethod() }During Xamarin.Android packaging, we would fix
MyHelloto be:class MyHello : IHelloJava8 { public void A () {} public void DefaultMethod() { HelloJava8.InvokeDefaultMethod (this); } }This would extend the existing support for versioned interfaces in a natural manner, causing the generated method implementation to invoke the default method instead of throwing an exception.
While all of those choices have problems, their severity on the issues are different.
I believe 1) is the only choice we can take with least problem so far (and that's what we do right now). It is the most conservative and the safest on future API breakage than other choices. By choosing 2) or 3) you would have already brought troubles regarding IAudioRouting fixes.
dotnet/android@576fb98Default interface methods that "used to be non-default" can be "fixed" by binding authors to change "abstract" attribute on the method i.e.:
<attr path="/path/to/the/method" name="abstract">true</attr>It should be also noted that those binding authors should be responsible to API changes. They can be the only responsible party.
- Apart from the known obvious issue, IAudioRouting.OnRoutingChangedListener also exposed another issue: it is possible for Java8 to add a new base interfaces to an existing interface without API breakage when such new base interfaces only have default methods. If you blindly bind those default methods in C#, it (of course) results in API breakage (i.e. missing method implementation) to any implementor of the interface.
It should be noted that once we expose extraneous methods to implement, especially at generator level, and we find any fatal problem (like we did for IAudioRouting), we cannot go back to the original state because it would already bring API breakage to everyone. It is the worst scenario.
- is almost 1), plus that there is slight chance for some problem that extension method could bring future compatibility issue regarding member resolution, especially because it resides in the same namespace as the primary interface.
Having said that 3) is worth implementing and probably even providing as an opt-in feature.
Reacted by Jason RaiPlease fix because we cannot use the latest ExoPlayer.
Reacted by Martijn van Dijk and SergheiYou should report specific, individual, actual issues as a new issue, not here without details.
The support for default interface methods is implemented at #341 (when I was at Xamarin)
- added a commit that references this issue
on Aug 1, 2019 - added a commit that references this issue
on Aug 24, 2019 - added a commit that references this issue
on Aug 30, 2019 Release status update
A new Preview version of Xamarin.Android has now been published on Windows that includes the new capabilities related to this item. See the release notes for additional details.
The new functionality is not yet available on macOS. I will update this item again when a Preview version with the new functionality is available on macOS.
Feature included in Xamarin.Android 10.0.99.100.
Feature included on Windows in Visual Studio 2019 version 16.4 Preview 1. To try the Preview version that includes the fix, check for the latest updates in Visual Studio Preview.
Feature not yet available on macOS.
Release status update
A new Release version of Xamarin.Android has now been published on Windows that includes the new capabilities related to this item. See the release notes for additional details.
The new functionality is not yet published in a Release version on macOS. I will update this item again when a Release version with the new functionality is available on macOS.
Feature included in Xamarin.Android 10.1.0.30.
Feature included on Windows in Visual Studio 2019 version 16.4. To get the new version that includes the feature, check for the latest updates or install the latest version from https://visualstudio.microsoft.com/downloads/.
(Feature also included on macOS in Visual Studio 2019 for Mac version 8.4 Preview 2.1 and higher. To try the Preview version that includes the feature, check for the latest updates on the Preview updater channel.)
Release status update
A new Release version of Xamarin.Android has now been published on macOS that includes the new capabilities related to this item. See the release notes for additional details.
Feature included in Xamarin.Android 10.1.1.0.
Feature included on macOS in Visual Studio 2019 for Mac version 8.4. To get the new version that includes the feature, check for the latest updates on the Stable updater channel.
- locked and limited conversation to collaborators
on Apr 15, 2024 - added a commit that references this issue
on Jul 1, 2026 - added a commit that references this issue
on Oct 8, 2026
Android N uses new Java 8 language features such as interface default methods and interface static methods, which are features that
tools/generatorhasn't had to deal with before.The question: how should they be dealt with?
There are at least three ways to do so:
Ignore them
Interface default methods don't need to be implemented, and static methods aren't implementable. The binding mechanism could thus simply ignore them entirely.
This isn't entirely desirable, because it also means default interface methods can't be called.
On the plus side, implementors don't need to worry about them:
Expose them
The "simple" version of "expose them" is do the simple thing:
staticmethods are bound in the constant-containingstaticclass, anddefaultmethods are bound as normal methods:This allows calling both methods:
However, this means that C# subclasses need to implement all the default methods:
This might not seem bad in this example, but java.util.Collection contains five default methods (one inherited from
Iterable).This might be fine and acceptable, and we could help this scenario by providing access to the default method implementation:
However, such "help" will require documentation and training to know about, complicating use.
Treat them specially
To a large extent, the concern is around C# implementations of the interface. It is seen that requiring that optional methods be implemented will complicate the C# experience. Perhaps we can fix this by splitting out the optional methods?
Then, we can use extension methods to invoke the default methods:
This allows calling both methods:
It also means that C# types don't need to implement the default methods:
...but if the C# type does want to implement them, they can all be implemented by using the
IDefaultMethodsinterface: