代码之家  ›  专栏  ›  技术社区  ›  Gabriel

在不同的泛型实例上实现相同的接口

  •  19
  • Gabriel  · 技术社区  · 16 年前

    interface IFoo<T> { void Foo(T x); }
    
    class Bar : IFoo<int>, IFoo<float>
    {
        public void Foo(int x) { }
        public void Foo(float y) { }
    }
    

    type IFoo<'a> = abstract member Foo : 'a -> unit
    
    type Bar() =
        interface IFoo<int> with 
            [<OverloadID("int")>]
            member this.Foo x = ()
    
        interface IFoo<float> with 
            [<OverloadID("float")>]
            member this.Foo x = ()
    

    'IFoo<float>' 'IFoo<int>' 。此版本的F#不允许这样做。

    我找不到 discussion of this issue

    2 回复  |  直到 13 年前
        1
  •  11
  •   Abel    10 年前

    .特点 has been planned 并且至少部分地(见注释)在F#4.0中实现。

    编辑

    public interface IG<T>
    {
        void F(T x);
    }
    public class CIG : IG<int>, IG<string>
    {
        public void F(int x) { Console.WriteLine("int"); }
        public void F(string x) { Console.WriteLine("str"); }
    }
    

    let cig = new CIG()
    let idunno = cig :> IG<_>  // type IG<int>, guess just picks 'first' interface?
    let ii = cig :> IG<int>    // works
    ii.F(42)                   // prints "int"
    let is = cig :> IG<string> // works
    is.F("foo")                // prints "str"
    

    所以这就是通常在这个“边界”上发生的事情,F#可以很好地使用这些东西,即使你不能在语言中编写相同的东西。

        2
  •  1
  •   Tom DeMille    10 年前

    有一种合理但不优雅的方法,为每个接口创建一个新类型。这里是一个从ESB(nSvcBus)消费多个事件的示例,它要求每个事件对应一个已实现的接口。下面的第一种类型包含泛型“处理程序”代码,其他类型只实现接口并调用泛型处理程序

    type public nSvcBusEvents() = 
    
        member this.HandleEvents(msg:IEvent) = ()
            //handle messages ie: let json = JsonConvert.SerializeObject(msg)
    
    type public ActionLoggedHandler() = 
        interface IHandleMessages<Events.ActionLoggedEvent> with
            member this.Handle(msg : ActionLoggedEvent) = 
                nSvcBusEvents().HandleEvents(msg)
    
    type public ActionCompletedHandler() = 
        interface IHandleMessages<Events.ActionCompletedHandler> with
            member this.Handle(msg : ActionCompletedHandler) = 
                nSvcBusEvents().HandleEvents(msg)
    
    type public ActionFailedHandler() =       
        interface IHandleMessages<Events.ActionFailedHandler> with
            member this.Handle(msg : ActionFailedHandler) = 
                nSvcBusEvents().HandleEvents(msg)