How to use two interface in this kind of writing ?
-
Thursday, January 26, 2012 10:14 AM
practicing how to templatize a factory pattern from c++ to F#
but mimic code has some problems such as
1. new IConcreteProduct() <- how it would be in F#
2. let x = new ConcreteCreatorClass(); <- how to pass instance that use interface to this class?
3. how to call let y = x.createProduct()?
4. is it using interface like this "let IConcreteProduct ConcreteProduct = "?
5. is it writing function for interface like this -- let ConcreteProductPrint = printfn "ConcreteProduct print" ?
6. any other wrong with the following writing
mimic code
open System type IProduct = abstract member ProductPrint : unit -> unit type IConcreteProduct = abstract member ConcreteProductPrint : unit -> unit type twoInterface = inherit IProduct inherit IConcreteProduct abstract member createProduct : unit -> unit type ConcreteCreatorClass() = interface twoInterface with member this.createProduct() = new IConcreteProduct() let IProduct Product = let ProductPrint = printfn "Product print" Console.WriteLine("") let IConcreteProduct ConcreteProduct = let ConcreteProductPrint = printfn "ConcreteProduct print" Console.WriteLine("") let x = new ConcreteCreatorClass(); let y = x.createProduct()Original code
template<typename Product, typename ConcreteProduct> class ConcreteCreator { public: static Product* createProduct() { return new ConcreteProduct(); } }; Product* p = ConcreteCreator<Product, ConcreteProduct>::createProduct();- Edited by Spidarman Thursday, January 26, 2012 10:15 AM
Answers
-
Monday, January 30, 2012 11:47 AM
Hi, the code I've posted is suitable for class inheritance only.
To use it with interfaces, you should do the following correction:
if not(typeof<'a>.IsSubclassOf(typeof<'b>)) && not(typeof<'a>.GetInterfaces().Contains(typeof<'b>)) then raise <| InvalidCastException()
- Marked As Answer by Spidarman Tuesday, January 31, 2012 8:33 AM
-
Tuesday, January 31, 2012 8:12 AM
.GetType()=(typeof<'b>) <<- that's totally incorrect. GetInterfaces returns an array of interfaces that are supported by specified type. You should use Contains here. It is a LINQ function. To use it, you must open System.Linq- Marked As Answer by Spidarman Tuesday, January 31, 2012 8:33 AM
All Replies
-
Thursday, January 26, 2012 11:08 AM
That is impossible in F# to specify that ConcreteProduct must inherit Product as long as they are both generic type parameters, so that compiler would check this. But you may use runtime type casts here to get desired results.
type IProduct = abstract member ProductPrint : unit -> unit type ConcreteProduct() = interface IProduct with member this.ProductPrint() = printfn "Concrete product" type ConcreteCreator<'b, 'a when 'a : ( new : unit -> 'a ) > private () = // single type check static do if not(typeof<'a>.IsSubclassOf(typeof<'b>)) then raise <| InvalidCastException() static member createProduct(): 'b = box(new 'a()) :?> 'b // this would work let product = ConcreteCreator<IProduct, ConcreteProduct>.createProduct() // this will at runtime, since ConcreteProduct does not derive from IEnumerable let fail = ConcreteCreator<System.Collections.IEnumerable, ConcreteProduct>.createProduct()
-
Friday, January 27, 2012 2:03 AM
System.TypeInitializationException was unhandled
Message: 'ConcreteCreator`2'at box(new 'a()) :?> 'b
debug can not see type parameter 'a and 'b
it seems to cast instance a' into type 'b, it has already checked whether using interface with IsSubclassOf, why need to cast
i feel the factory is a collection of different abstract type of instances
- Edited by Spidarman Friday, January 27, 2012 2:06 AM
-
Friday, January 27, 2012 8:14 AM
> it seems to cast instance a' into type 'b, it has already checked whether using interface with IsSubclassOf, why need to cast
The fact that we know at runtime, that 'a is subclass of 'b does not mean that compiler can get rid of cast, because compiler acts at compile time.
By the way, that is fail of F#. C# does support " 'a must be subclass of 'b " constraint. So you can add an auxiliary library in C#, which would not require neither dynamic type check, nor dynamic cast.
or this way, whatever you like:public class ConcreteCreator<I, C> where C: I, new() { public static I createProduct(){ return new C(); } }
public class ConcreteCreator<I> { public static I createProduct<C>() where C: I, new(){ return new C(); } }- Edited by lostmsu Friday, January 27, 2012 8:20 AM
-
Monday, January 30, 2012 2:29 AMHi , how to fix error System.TypeInitializationException was unhandled
it seems can not run -
Monday, January 30, 2012 11:47 AM
Hi, the code I've posted is suitable for class inheritance only.
To use it with interfaces, you should do the following correction:
if not(typeof<'a>.IsSubclassOf(typeof<'b>)) && not(typeof<'a>.GetInterfaces().Contains(typeof<'b>)) then raise <| InvalidCastException()
- Marked As Answer by Spidarman Tuesday, January 31, 2012 8:33 AM
-
Tuesday, January 31, 2012 2:36 AM
Hi, run your code, the error at box(new 'a()) :?> 'b
and the GetInterfaces() do not have contains, it seems GetType() = (typeof<'b>) can be compiled
open System
type IProduct =
abstract member ProductPrint : unit -> unit
type ConcreteProduct() =
interface IProduct with
member this.ProductPrint() = printfn "Concrete product"
type ConcreteCreator<'b, 'a when 'a : ( new : unit -> 'a ) > private () =
// single type check
static do if not(typeof<'a>.IsSubclassOf(typeof<'b>)) && not(typeof<'a>.GetInterfaces().GetType()=(typeof<'b>)) then raise <| InvalidCastException()
static member createProduct(): 'b = box(new 'a()) :?> 'b
// this would work
let product = ConcreteCreator<IProduct, ConcreteProduct>.createProduct() -
Tuesday, January 31, 2012 4:29 AM
not familiar with list operation after using isAllZeroes list
it seems that it is not list and can not be used by List, After googled, nothing about list but have List
just want to find if one of items false and then return false, otherwise return true
open System type IProduct = abstract member ProductPrint : unit -> unit type ConcreteProduct() = interface IProduct with member this.ProductPrint() = printfn "Concrete product" let checkTypeList(a : Type[], b) : Boolean = let isAllZeroes list = Seq.forall (fun elem -> elem.GetType()=b) a let mutable result = true result <- List.find (fun item -> item = false) isAllZeroes if result = false then false else true type ConcreteCreator<'b, 'a when 'a : ( new : unit -> 'a ) > private () = // single type check static do if not(typeof<'a>.IsSubclassOf(typeof<'b>)) && not(checkTypeList(typeof<'a>.GetInterfaces(), typeof<'b>)) then raise <| InvalidCastException() static member createProduct(): 'b = box(new 'a()) :?> 'b // this would work let product = ConcreteCreator<IProduct, ConcreteProduct>.createProduct()- Edited by Spidarman Tuesday, January 31, 2012 4:30 AM
-
Tuesday, January 31, 2012 8:12 AM
.GetType()=(typeof<'b>) <<- that's totally incorrect. GetInterfaces returns an array of interfaces that are supported by specified type. You should use Contains here. It is a LINQ function. To use it, you must open System.Linq- Marked As Answer by Spidarman Tuesday, January 31, 2012 8:33 AM
-
Tuesday, January 31, 2012 8:33 AMit have contains now, it can run. Marvelous.

