When I want to use method AddTwo() I need to cast the object of class One to interface IOne:
1 2let simpleAdd = new One() let test = (simpleAdd :> IOne).AddTwo(2)For me this use of method defined in the interface implemented by the class is unacceptable.
Basically because the code that uses class One needs to be aware what interfaces the class implement, and what methods belong to that interface, this just brakes encapsulation.
The problem is that you're actually confusing things. F# enforces encapsulation by making you aware of your interfaces.
What it's trying to tell you is that if you want to do operations on "IOne" types then you should be a bit more explicit about it.
This is one of the cases where type annotations come in handy like this:
1 2 3 4 5 6 7 8 9 10
#light type IOne = abstract AddTwo : int -> int type One() = interface IOne with member this.AddTwo i = i + 2 let addTwo (t:IOne) = t.AddTwo let test = addTwo (new One()) print_any (test 2)
As you can see the "test" method can seamlessly pass a One as a IOne. And this is should be the common case that who ever is doing an operation know what protocol/interface to follow and you encode that with types when needed.
This is no different than in C# following the rule to use the least specific interface/class possible to get the job done.
It promotes encapsulation by making you think about what is really needed to accomplish a task in essence driving complexity down.
Hi,
I agree that this is a limitation, but I encounter it only very rarely when writing code in F#. I think it is because if you're writing code in F# (even when using object types and interfaces), you don't need as many classes as in C#, because there is often easier way to solve the problem. If you're required to write very object-oriented code (for example because it is a library used by C# client) then it is probably easier to use C# - but you can still write some core parts in F#.
Anwyay, in the case you mentioned, you can use obejct expressions and achieve the same thing more elegantly:
1 2 3 4 5 6 7
type IOne = abstract AddTwo : int -> int let simpleAdd = { new IOne with member x.AddTwo(i) = i + 2 } let test = simpleAdd.AddTwo(2)
I think it is important to keep in mind that the design of F# programs is a bit different then when writing C# programs, but if you find the right way then it becomes very elegant & easy to write. If you want to post some more real-world example of what you're doing then we may give you some better hints!
Hope this helps!
Tomas
Thanks, however I just want to get elegant code in general.
If you had just one interface and let's say five classes implemnting it, the code would look like jungle. You would have two options:
1) making your code awful by adding additional methods. How to name them?
2) forcing people using your code to cast every object ;) so annoying, and I am not a fan of casting.
I mean that the way the OOP part of F# is now made, brakes many good programming practices. There is no good way to walk around this problem.
Do you know if they are going to address this problem in next release?
Regarding option 1 and 'how to name', use the exact same name and signature. Then you'll have a class that's much like what you get in C#, the only difference being you have to define both the interface method and the class method (whose implementation just delegates to the interface), whereas in C# you just define the class method (and it automatically fills the interface slot as well).
We'll consider this suggestion for the next release. But I echo Tomas' comment that this doesn't occur too often in practice, especially when programming with 'F# style'.
I agree that this is less of an issue when you program in a functional style.
IMO, the practical issue here is more about interoperability with C#. Right now I am starting to write new code in my legacy C# code base in F#. One way I have started swaping out some of the old C# code with f# is to impliment interfaces from some of the C# code.
It is probably a good idea to make this transition process (and interoperability in general) as smooth as possible
Coming from Java & C#, I find having to cast up to the interface type in this situation to be a bit strange and verbose. May be I'll get used to it. Is it possible to eliminate the need to do the upcast? Or is this truly a better design?
1 2 3 4 5 6 7 8 9
type IMathService = abstract Multiply : int * int -> int type MathService() = interface IMathService with member x.Multiply(a:int, b:int) = a * b let math = new MathService() :> IMathService let result = math.Multiply(5,4)
See F# Manual, 8.5 Interface Specifications and Implementations
"Interface members are called by first casting to the interface type:"
[link:research.microsoft.com]
You need the upcast. I think the other messages on this thread describe this well in detail.
Yes, I realize that that the upcast is required in the current design/implementation of F#. I'm curious if there has been any thought to removing the need for an upcast in the design of the F# language. I do not know if that would be a good design decision or not.
In two of my previous posts I said
We'll consider this suggestion for the next release.
and
I don't know what 'the right/best answer is', but I hope this illuminates the issues that play into the pros and cons of have interface methods automatically show up on concrete class types.
So yes, we will think about it; there are pros and cons and it's not necessarily totally clear to us if it's 'good' or not either.
Brian -- I appreciate your williingness not to prejudge the issue.
Here's a case where I think having to explicitly upcast causes clutter and interferes with a straightforward way of composing API calls.
For example, suppose Layer, SpecialLayer, Sum, Minimum and Contract all implement IFoo interface which has a single method Foo. Also, Sum and Minimum work on List<IFoo> , and Contract takes an IFoo argument.
I'd like to write:
1 2 3 4
let layer1 = Layer( 100000, 10000) let layer2 = SpecialLayer( 30000, 15000) let layer3 = Sum[ layer1 ; layer2 ] let contract = Contract( Minimum[ layer1 ; l ayer2 ; layer 3 ] )
and pass the resulting contract to a solver.
Currently I have to write:
1 2 3 4 5 6 7
let layer1 = Layer( 100000, 10000) :> IFoo let layer2 = SpecialLayer( 30000, 15000) :> IFoo let layer3 = Sum[ layer1 ; layer2 ] :> IFoo let contract = Contract( Minimum[ layer1 ; l ayer2 ; layer 3 ] :> IFoo )
to which I say, er, 'fooey'.
David
This is a separate issue from having to upcast to call methods on IFoo; this is subsumption for list literals. I think you may be happy with us in the near future. :)
Actually, I'm pretty happy with you guys already, but am always willing to get happier;>
fyi, we just released with this feature
More flexibility for list literals and subtyping
List and array literals may now be used to create collections from elements that are subtypes of the collection element type. For example:
let myControls: (Control list) = [ new Button() ; new TextBox() ]
Thanks, can write cleaner and clearer code without the casts!
Plus I neverused to knew what 'list literal subsumption' was.
thanks David
ps. On another Oct09 release topic, why do we have to add "when 'a: comparison" -- can't the compiler figure it out? Here's an example --
1 2 3 4 5 6 7 8 9 10 11
type Ordering< 'a > = | Order of 'a * 'a | NotComparable type PartialOrderedSet< 'a when 'a : comparison >( ordering: Map< 'a, Set < 'a > > ) = member x.Compare a b = match a, b with | a, b when ordering.ContainsKey(a) && ordering.[ a ].Contains(b) -> Order(a,b) | a, b when ordering.ContainsKey(b) && ordering.[ b ].Contains(a) -> Order(b,a) | _ -> NotComparable
I think Don plans to blog in detail about the motivation and details of the new equality/comparison constraints in the near future.
Old thread, but I wanted to ask about something that's related to this.
Consider the followeing code:
1 2 3 4 5 6 7 8
type I1 = abstract M1 : string abstract M2 : string type C1 = interface I1 with override c.M1 = "hello" override c.M2 = (c:>I1).M1
Why should I have to upcast to I1 from within the M2 implementation? It is already within the context of the I1 implementation.
I know that naming conflicts could arise if C1 has other methods with the same name, but I think that the implicit behavior in this case would be to resolve names to within the interface first and perhaps downcast to access the same name at class level.
I recall there was also some vague talk of maybe providing some syntactic sugar for implicit interface implementation, but I don't see anything like that in beta 2. Am I missing something, or is it really not there? If not, is it planned for release?
No, there is nothing there/planned. Note however that regarding (explicit) interfaces, we have fixed some bugs, e.g. as mentioned in the release notes:
Interface implementations can now be inherited
Interfaces implemented by inherited classes can be used to satisfy interface implementation requirements on a derived class. Code such as the following now compiles without the need to explicitly implement I1 in C2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
type public I1 = abstract V1 : string type public I2 = inherit I1 abstract V2 : string type public C1() = interface I1 with member this.V1 = "C1" type public C2() = inherit C1() interface I2 with member this.V2 = "C2"
tomasp, I think that using additional function to use a part of class's methods is just wrong, and would be hard to understand for someone who has no idea about F#.
brianmcn, You convinced me to stick with option 1), I still thinks that every redundancy is bad, and just asks for mistakes.
Can You summarize why F# doesn't have interfaces and inheritance known in C#?
Btw, I've read "Expert F#", Could You recommend where I can read about good practices in F#?
C# has explicit interfaces too:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public interface IFoo { void Method(); } public class Foo : IFoo { void IFoo.Method() { } public static void Example() { Foo foo = new Foo(); foo.Method(); // does not compile (foo as IFoo).Method(); // does } }
The differences are that in F#, interfaces are implemented explicitly by default, whereas in C# they are not, and that in F# there is no syntax to have one method implement both.
The value of explicit interfaces is that they can help reduce complexity and make code more explicit. With many interfaces, you would never call the method on a concrete object, you would only call it on an object that was already upcast to the type. That is, often you'll have a class implement an interface, not so that a user will new up the class and call the method, but instead because a user will new up the class and hand it to some framework that knows how to process IFoos or whatever. In that case, the framework will just keep a collection of IFoo objects and call those methods. When a user does "myFoo." and the intellisense comes up, if IFoo is implemented explicitly, the IFoo methods don't appear, reducing the user-facing complexity for common user scenarios. (Try newing up some WPF objects and look at the hundreds and hundreds of methods that appear in intellisense. How many of those are you likely to call? How many of those are only there to support interaction with other parts of WPF framework? Wouldn't it be nice if more of those interfaces you don't care about were out of your face?)
On the other hand, there are also cases where the interface methods are also intentionally user-facing. List : IList is a good example. Users who have just newed up a List will call Add(), Clear(), etc. But also general methods that work on arbitrary-concrete-collection ILists will also call these methods. In this case, you don't want the interface to be explicit, you want both the users of the concrete type and users targeting the interface to see the same method.
C# prefers the latter strategy, but has a little-known and little-used syntax support for the former. F# prefers the former strategy, and has no syntax sugar for the latter (which is why you have to 'repeat yourself').
I don't know what 'the right/best answer is', but I hope this illuminates the issues that play into the pros and cons of have interface methods automatically show up on concrete class types.
Can I plead to the designers and caretakers of F# to keep this the way it is?
Please! For the love of all things simple and clean.
Yes comming from a C++ and C# background I stumbled and fell on this issue, I even started argumenting that it was broken flawed and a complete and utter disgrace.
But I was wrong. Dead wrong. The thing is that the F# behaviour promotes among other things IoC and makes it clear what my dependencies really are. It helps keep methods small and focused.
In the example of using a List<T> as an IList<T> to Add/Clear/DoStuff not having the implicit usage actually helps separate the creating of a concrete class from the abstract filling. And that's a good thing.
It helps us bring forth the structure and beauty of interface segregation and helps us think about what the minimal interface needed for an operation really is.
I agree with torbjorn.gyllebring 110%!
Hi,
I think the key point is that in F# you don't usually have classes that implement an interface (that would be used directly by the user of the class) and add lot of new functionality by having additional members.
When you just want to implement an interface then object expressions are often the best option. However you can use classes too - and you don't need casting if you just want to call a method/function that takes the interface as an argument:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
type IFoo = abstract Foo : unit -> unit let callFoo(f:IFoo) = f.Foo() type Foo1() = interface IFoo with override x.Foo() = printfn "Foo1" type Foo2() = member x.Other() = printfn "Other" interface IFoo with override x.Foo() = printfn "Foo2" let f1 = new Foo1() let f2 = new Foo2() // Call function that works with the interface callFoo f1 callFoo f2 // we can still use other members f2.Other()
So, I think that F# just forces you to separate parts of the code that works with interfaces implemented by the class and parts that use additional members.
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hello,
I've wanted to write simple application in F# and I've encountered one significant flaw in F#.
In the code
When I want to use method AddTwo() I need to cast the object of class One to interface IOne:
For me this use of method defined in the interface implemented by the class is unacceptable.
Basically because the code that uses class One needs to be aware what interfaces the class implement, and what methods belong to that interface, this just brakes encapsulation.
tomasp in the post [link:cs.hubfs.net] proposed to create additional methods in the class, however this approach brakes rule "Don't repeat yourself".
That is way I'd like to know if this problem will be solved?
When I think about using interfaces and inheritance the way it is now, it makes me start thinking of writing the code in C#.
It is normal in application to have many classes and interfaces, and I just can't imagine myself writing such an annoying additional code.