hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

interface of object expressions

Last post 11-20-2007, 17:12 by dsyme. 4 replies.
Sort Posts: Previous Next
  •  11-20-2007, 2:48 4096

    interface of object expressions

    Hello.

    How can I retrieve an interface of an object created via object expressions?
    All of my tries failed :-(

    #light

    type c = class new () = {} end;;
    type d = interface abstract f: int end;;
    let x = { new c () interface d with member self.f = 3 };;

    (* no definition below type checks *)
    let x1 = (x :> d);;
    let x2 = (x :? d);;
    let x3 = (x :?> d);;
    let x4 = x.f;;

    Best regards,
    keiko

  •  11-20-2007, 3:16 4098 in reply to 4096

    Re: interface of object expressions

    Hi,
    this is similar to a problem discussed here: http://cs.hubfs.net/forums/thread/3616.aspx. Basically, this is a limitation in the F# language, which allows using ":?>" operator only when the target type (interface d in your case) is inherited from the source type (interface c in your case). This is unnecessary limitation for interfaces (but it is useful for classes), so the limitation for interfaces will be probably removed in a future version.

    In the meantime you can use following:


    let dynamic_cast o = (box o) :?> 'a
    let x5 : d = dynamic_cast x


    Tomas Petricek (Blog), C# MVP
    My book: Real-world Functional Programming in .NET
  •  11-20-2007, 7:32 4100 in reply to 4098

    Re: interface of object expressions

    Thank you for the explanation;
    but I do not understand "but it is useful for classes" of the following sentence: 
    
    > This is unnecessary limitation for interfaces (but it is useful for classes),
    
    Could you explain to me more concretely?
    
    In fact, the reliance on the dynamic type test already looks a limitation.
    I thought that the type system could deduce 
    the fact that x implements the interface d.
    
    Best regards,
    keiko
  •  11-20-2007, 13:47 4106 in reply to 4100

    Re: interface of object expressions

    Hi,
    I did a few mental steps without explaining them, so let me clarify this.

    Object expressions in F# are really (currntly) intended only for implementing a single interface type, which means that the type of the expression is just this interface type. You cannot for example add new members, because the return type is the interface that you're impementing and there wouldn't be any (reasonable) way for accessing the members. I'm a bit surprised that the syntax allows implementing multiple interfaces, because as far as I know this isn't currently the intended use (but I think that it makes very good sense and that it would be nice to support this in the future by returning a type that implements both interfaces - this is probably a bit difficult to implement technicall in .NET, but I think it should be possible). So that's I think why it doesn't work without dynamic tests.

    The restriction for classes is sometimes useful - for example let's say you have a base class A, class B inherited from A and some completely unrelated class C. When you have instances a, b and c the compiler will do the following:


    a :?> B // allowed because B inherits from A so 'a' can be instance of B upcasted to type A
    c :?> B // not allowed because instance of type C cannot contain a value that
    // could be casted to B (because .NET supports single implementation inheritance)

    However - these restrictons don't work well or inerface types, because a class can implement multiple intrfaces.


    Tomas Petricek (Blog), C# MVP
    My book: Real-world Functional Programming in .NET
  •  11-20-2007, 17:12 4112 in reply to 4106

    Re: interface of object expressions

    On the object expression question, see

    http://research.microsoft.com/fsharp/manual/advanced.aspx#ObjectExpressions, where it says this:

    Objects created via object expressions can also support multiple interfaces.. The syntax is:

       { new  with 
         interface  with 
         ...
         interface  with  }
    

    e.g.,

        { new Object()
            with Finalize() = cleanupFunction(false);
            
          interface IDisposable 
            with Dispose() = cleanupFunction(true);  } 
    

    The interfaces are not part of the type of the object expression but can be revealed through type tests.

View as RSS news feed in XML
Powered by Community Server, by Telligent Systems