Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object expressions should allow for new interface implementations, and fit into parameters of said interface #944

Closed
5 tasks done
Happypig375 opened this issue Dec 31, 2020 · 6 comments

Comments

@Happypig375
Copy link
Contributor

Happypig375 commented Dec 31, 2020

I propose we allow

let videoView = new Android.Widget.VideoView(context)
videoView.SetOnPreparedListener({
    new Java.Lang.Object() with
        interface Android.Media.MediaPlayer.IOnPreparedListener with
            member _.OnPrepared player = () })
// Currently fails with
// FS0010 Incomplete structured construct at or before this point in expression. Expected '}' or other token.	
// FS0583 Unmatched '('
// FS0193 Type constraint mismatch. The type 'Java.Lang.Object' is not compatible with type 'Android.Media.MediaPlayer.IOnPreparedListener'
// FS0604 Unmatched '{'
// FS0010 Unexpected keyword 'interface' in object expression. Expected 'member', 'override' or other token.
// FS0010 Unexpected start of structured construct in object expression

The existing way of approaching this problem in F# is writing a boilerplate class.

Pros and Cons

The advantages of making this adjustment to F# are

  1. Better interop with Xamarin.Android
  2. Expand the use cases of object expressions
  3. Help write more concise code.

The disadvantage of making this adjustment to F# is that object expressions may be too niche to be improved. However, it is a niche exactly because of cases like these where it cannot be used.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions: (put links to related suggestions here)

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@FunctionalFirst
Copy link

I think this may be related to the fact that it isn't possible to implement an abstract class using object expressions without overriding at least one member (see related SO question). You can work around this limitation by overriding one of System.Object's virtual members.

let videoView = new Android.Views.VideoView(context)
videoView.SetOnPreparedListener({
    new Java.Lang.Object() with
        member _.ToString() = base.ToString()
    interface Android.Media.MediaPlayer.IOnPreparedListener with
        member _.OnPrepared player = () })

@Happypig375
Copy link
Contributor Author

@FunctionalFirst
image
(Sorry for wrong namespace btw)

@FunctionalFirst
Copy link

@Happypig375 You're right—my mistake. There were no squiggles, but I see the same error if I send to interactive.

@charlesroddie
Copy link

charlesroddie commented Jan 8, 2021

The existing way of approaching this problem in F# is writing a boilerplate class.

I.e.

type private ListeningJavaObject() =
    inherit Java.Lang.Object()
    interface Android.Media.MediaPlayer.IOnPreparedListener with
        member _.OnPrepared player = ()
let videoView = new Android.Widget.VideoView(context)
videoView.SetOnPreparedListener(ListeningJavaObject())

If the intention of allowing the proposed code over the explicit class is to save one line, that not a real advantage. If the intention is to allow a more local definition, then #150 would be better way to do it, although a much larger feature to implement. But since there are several new issues about anonymous classes and interfaces it might be considered instead of implementing all of those.

@amongonz
Copy link

@Happypig375 The underlying object still implements the interface, so you could unbox the object expression, but at the expense of static type checking.

The missing feature here is object expressions having an anonymous type when they inherit/implement more than one type. As for the unnecessary override for the parent type, #632 is approved, but missing an RFC.

@dsyme
Copy link
Collaborator

dsyme commented Jun 16, 2022

The missing feature here is object expressions having an anonymous type when they inherit/implement more than one type.

This is by-design, as it's useful and important to check that the interfaces are related to the type being implemented. We won't be adjusting that decision

As for the unnecessary override for the parent type, #632 is approved, but missing an RFC.

Yes, this is the rest of the matter here, covered by #632

@dsyme dsyme closed this as not planned Won't fix, can't repro, duplicate, stale Jun 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants