Is it possible for an object to refer to itself before member definitions? Something like this:
type public ClassA () = class
let b = new ClassB(this)
member public x.getClassB() = b
end
where 'this' is a reference to the instance of ClassA creating the ClassB?
Classes can refer to themselves in their constructors using as:
type public ClassA () as this =
let b = new ClassB(this)
member public x.getClassB() = b
and public ClassB (a: ClassA) =
member public x.getClassA() = a
Related
I wrote some code like
type internal IMyInterface =
abstract member Method1 : unit -> unit
type Class1() =
member this.Y() =
(this :> IMyInterface).Method1()
interface IMyInterface with
member this.Method1() = ()
Note that the public type Class1 implements an internal interface IMyInterface, it compiles fine. In the generated MSIL, "Method1" was shown as private. This is similar to explicit interfaces in C#.
However, when I change the code a bit to
type internal Foo() =
member x.Value = "Foo"
type internal IMyInterface =
abstract member Method1 : Foo -> unit
type Class1() =
member this.Y() =
let v = Foo()
(this :> IMyInterface).Method1(v)
interface IMyInterface with
member this.Method1(v : Foo) = ()
This type the interface method "Method1" takes an internal type "Foo" as parameter. This time, it does not compile with an error
The type 'Foo' is less accessible than the value, member or type 'override Class1.Method1 : v:Foo -> unit' it is used in
I have trouble to decipher this error message and find a fix for it. In C#, I can write the following code that compiles fine
internal class Foo
{
string Value { get; set; }
}
internal interface IMyInterface
{
void Method1(Foo v);
}
public class Class1 : IMyInterface
{
public void Y()
{
var v = new Foo();
(this as IMyInterface).Method1(v);
}
void IMyInterface.Method1(Foo v)
{
throw new NotImplementedException();
}
}
Any idea about the F# compiler error and how to work around it?
BTW: this may not be the right way/pattern to use interface anyway, I'm just curious on the language syntax
As it was pointed out at Patrick's comment, this issue was logged as a bug of Visual F#. Currently it's included in F# 4.0 Update 3 milestone.
I am having difficulty to convert following C# code to F#:
class Foo
{
public Foo() { }
public Foo(string name) { }
}
class Bar : Foo
{
public Bar() : base() { }
public Bar(string name) : base(name) { }
public string Name { get; set; }
}
I first tried following, but it is reporting error
Constructors for the type 'Bar' must directly or indirectly call its
implicit object constructor. Use a call to the implicit object
constructor instead of a record expression.
type Foo() =
new(name:string) = Foo()
type Bar() =
inherit Foo()
new(name:string) = { inherit Foo(name) }
member val Name:string = null with get, set
Then I tried following, but it is now reporting error on the auto property
'member val' definitions are only permitted in types with a primary
constructor. Consider adding arguments to your type definition"
type Foo() =
new(name:string) = Foo()
type Bar =
inherit Foo
new(name:string) = { inherit Foo(name) }
member val Name:string = null with get, set
If you want F# source code who compiles to precisely the same API as given by your C# code, the answer is as follows:
type Foo =
new() = {}
new(name:string) = { }
type Bar =
inherit Foo
[<DefaultValue>]
val mutable private name:string
new() = { inherit Foo() }
new(name) = { inherit Foo(name) }
member x.Name with get() = x.name and set v = x.name <- v
This compiles:
type Foo() =
new(name:string) = Foo()
type Bar(name : string) =
inherit Foo()
new() = Bar(null) // or whatever you want as a default.
member val Name:string = name with get, set
See Constructors (F#) and Inheritance (F#).
Looking at the decompilation, the C# would be (with attributes removed):
public class Bar : Program.Foo {
internal string Name#;
public string Name {
get {
return this.Name#;
}
set {
this.Name# = value;
}
}
public Bar(string name) {
this.Name# = name;
}
public Bar() : this(null) {
}
}
public class Foo {
public Foo() {
}
public Foo(string name) : this() {
}
}
If a class has a parameter list directly after its name (including ()), it has a primary constructor. Using it, any inherit declarations are placed only in this primary constructor, which comes directly after the class declaration and before any member declarations.
It is unclear what you are trying to achieve. The class Foo has a constructor taking a string argument, only to discard it. A (technically) valid, similar pair of classes would be this:
type Foo(name:string) =
member f.NameLength = name.Length
type Bar(initialName) = // WARNING: this will not end well
inherit Foo(initialName)
member val Name:string = initialName with get, set
But this is not sensible code. Foo will keep the initial name even if the name in Bar is changed. Bar.Name.Length returns the current name's length, while Bar.NameLength returns the initial name's length.
To keep the default constructor, one could add new () = Bar(null) (or the equivalent in Foo), but please note that null is considered an interop-only feature. It is not used in F# facing code; if possible, use the appropriate option type or an empty string respectively (depending on whether the string is just empty or doesn't exist at all).
Also, inheriting classes is discouraged in the F# component design guidelines -- for good reason. There are few use cases, but those usually involve a tiny base class and a derived class that is a perfect superset of it. It is far more common to compose types by using one class as a member of another.
I don't know how relevant this is, but here is an example of a class with default constructor and an additional constructor that uses it:
type Text500(text : string) =
do if text.Length > 500 then
invalidArg "text" "Text of this type cannot have a length above 500."
member t.Text = text
new () = Text500("")
This utilizes the primary constructor to verify input and has an additional, parameterless constructor that uses an empty string. (I'm not sure if the additional constructor would be useful in actual applications.)
I did not find a clear answer for this...
What is the F# equivalent of this C# code:
public class SomeClass
{
public virtual SomeMethod([Attribute] Int32 param)
{ }
}
Because there are two different places to put the attribute in F#:
type SomeClass () =
abstract SomeMethod : [<Attribute>] param:Int32 -> Unit
default this.SomeMethod ([<Attribute>] param) = ()
You can put it on both, but the override (default) is the one that counts.
type T =
abstract M : (* [<Out>] this is okay too *) i: byref<int> -> unit
default this.M([<Out>] i) = () //but this one's necessary
Given an F# type:
type Foo() =
member this.Prop with get() = ()
interface IDisposable with
member this.Dispose() = ()
In C#, I create the object, but I can't call Dispose():
var x = new Foo();
x.Dispose(); // compile error, x does not contain a definition of Dispose
However, I can write:
((IDisposable)x).Dispose(); // works, but I don't like the cast
Is there any way to avoid the cast in C#? Is this related to the way F# doesn't automatically let you call .Dispose() on the Foo type from within F#?
Interface implementations in F# are explicit by default. Hence the methods are not visible unless seen from the type converted to the interface (some form of casting).
To work around this expose an instance method which has the same signature as the interface version. Then have the interface on forward to the instance function. For example
type Foo() =
member this.Prop with get() = ()
member this.Dispose() = ()
interface IDisposable with
member this.Dispose() = this.Dispose()
How about, for this particular interface:
using (var x = new Foo()) {
...
}
How would this class look in f#?
public class myClass : baseClass
{
public myClass()
{
this.someVariable = "test";
this.someFunction();
}
}
So far i've figured out (is it even correct?):
type myClass = class
inherit baseClass
new ()=
this.someFunction()
end
but am struggling with calling someFunction() as it says 'this' is not defined
Here's one way to translate your code:
type baseClass() =
member this.someFunction() = printf "hello world\n"
type myClass() as this =
inherit baseClass()
let mutable someVariable = "test"
do this.someFunction()