tags:

views:

126

answers:

4

Is it possible to implement friend function and friend class (as in c++) in F#?

Update: Since there is no friend function/class in f#, and friend is not even a reserved keyword for future expansion, I'm wondering is there any problems with the friend mechanism in F# that make the developers to decide not to implement it? (such as in "protected" access modifier).

Suggestion 1: Brian, signature file - I don't think that this thing work properly. If you have a closure (e.g. lambda expression in A, which is a different object than the instance of A) that evaluate B.X , it's won't work

Suggestion 2: Massif (+Mitya0), InternalsVisibleTo - It's not clear to me, Are you writing this in the second class or it expose the class to the entire assembly?

+2  A: 

The concept of friends as it exists in C++ doesn't exactly translate to F#, but you can use the internal accessibility modifier to allow access to all classes in the same .NET assembly. This is probably what you are looking for.

J Cooper
`internal` is a blunt instrument, wield it with care.
Brian
internal is only blunt if your assemblies are big.
Mitya
@Mitya, yes, it is unfortunate that visibility boundaries that `internal` imposes rigidly coincide with assembly boundaries. :P
Brian
@Brian: I do agree with that.
Mitya
+1  A: 

From what I see of documentation, there is a friend notion in C#, but the same documentation suggests F# doesn't have this ability.

Brent Arias
Everything in documentation you cite applies to F#, including InternalsVisibleTo attribute
Mitya
+7  A: 

Note that you can use signature files to mimic friend.

If you want A to be a friend of B, so A can access internals of B that others cannot see, you can do e.g.

// File1.fs
type B() =
    let x = 42  // private field
    member this.X = x // public getter

type A() =
    member this.PeekInto(b : B) =
        b.X

but also have

// File1.fsi
type B = 
    new : unit -> B
    // do not expose X in the signature

type A = 
    new : unit -> A
    PeekInto : B -> int

and now A's implementation can see B.X but the sequel of the program cannot see B.X.

Signature files are pretty awesome for creating arbitrary encapsulation boundaries.

Brian
I like this solution!
J Cooper
I do too - signature files are kinda one of the most awesome features of the language that no one seems to know about (see http://stackoverflow.com/questions/181613/hidden-features-of-f/1844881#1844881 )
Brian
Yes - it is unfortunate that visibility boundaries that signatures impose currently rigidly coincide with file boundaries
Mitya
@Mitya, yes, give people a useful new feature and all they do is complain that it's not flexible enough. :)
Brian
@Brian: fsi files are not new - it is a cut down version of modules and module signatures from OCaml.
Mitya
+1  A: 

As mitya has pointed out. Just use the InternalsVisibleTo attribute on the class you want to see the protected members of, or on the entire assembly. (I do this all the time for unit testing purposes).

[<assembly:System.Runtime.CompilerServices.InternalsVisibleTo("UnitTestModule")>]

Works a treat.

Massif