具有通用字段类型的多态 [英] polymorphism with types for common fields

查看:70
本文介绍了具有通用字段类型的多态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是否可以通过惯用功能方法解决,泛型歧视工会会是答案吗?

Is this question solvable through functional idiomatic approach, could generics or discriminated unions be the answer?

当函数使用一些公共字段时,是否可以通过将不同的类型传递给函数来实现多态.

Is it possible to have polymorphism with passing different types to a function while the function is consuming some common fields.

想法应能够调用和重用具有不同类型的函数,并使用公共属性/字段.

Idea is to be able to call and reuse the function with different types and use the common attributes/fields.

type Car = {
    Registration: string
    Owner: string
    Wheels: int
    customAttribute1: string
    customAttribute2: string
}

type Truck = {
   Registration: string
   Owner: string
   Wheels: int
   customField5: string
   customField6: string
}


let SomeComplexMethod (v: Car) = 
    Console.WriteLine("Registration" + v.Registration + "Owner:" + v.Owner + "Wheels" + v.Wheels
    // some complex functionality

使用

SomeComplexMethod(car)
SomeComplexMethod(truck)


修改

按照答案.是否可以指定传入的v的类型,因为JSON序列化程序要求关联的类型.如果提供了轿厢作为输入,则将输出轿厢,如果输出卡车作为输入,则将输出卡车.

Following the answer. Is it possible to specify the type of the incoming v since JSON serializer asks for the associated type. If Car was supplied as input, Car will be output, If truck as input truck will be output.

let inline someComplexFun v  =
    let owner =  (^v: (member Owner: string)(v)) 
    let registration = (^v: (member Registration: string)(v))
    // process input

    use response = request.GetResponse() :?> HttpWebResponse
    use reader = new StreamReader(response.GetResponseStream())
    use memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))
    (new DataContractJsonSerializer(typeof<Car>)).ReadObject(memoryStream) :?> Car

如果卡车是输入v

(new DataContractJsonSerializer(typeof<Truck>)).ReadObject(memoryStream) :?> Truck

推荐答案

您想要的通常称为结构(或鸭子)类型化.可以通过F#中的接口和对象表达式(可接受的方式)或通过SRTP来完成. @CaringDev提供的链接为您提供了快速的概览,但是显然您可以找到更多示例.请阅读

What you want is usually called structural (or duck) typing. It can be done via interfaces and object expressions in F# (the accepted way) or via SRTPs. The link @CaringDev provided gives you a quick rundown, but obviously you can find many more examples. Please read this and this. For your specific example it will depend how much control you have over the original types.

定义包含您可能想要的字段的另一种类型很容易.然后,您的函数(我发现它很有趣,顺便说一句,您非常想寻求一个功能解决方案,但将其命名为方法...)应该只采用具有必需字段/属性的任何类型.在这种情况下,泛型将对您不起作用,因为您需要限制为类型的子集.但是一旦有了这样一个使用静态解析类型参数(SRTP)的函数,您就可以开始:

It's easy to define another type that includes the fields that you might want. Then your function (I found it interesting btw, that you so much want to go for a functional solution but named it a method...) should just take ANY type that has the required fields/properties. Generics won't work for you in this case, as you need to constrain to a subset of types. But once you have such a function, which uses statically resolved type parameters (SRTPs) you're good to go:

type Car = {
    Registration: string
    Owner: string
    Wheels: int
    customAttribute1: string
    customAttribute2: string
}

type Truck = {
   Registration: string
   Owner: string
   Wheels: int
   customField5: string
   customField6: string
}

type Bike = {
    Owner: string
    Color: string
}

type Vehicle = {
    Registration: string
    Owner: string
}

let inline someComplexFun v  =
   let owner =  (^v: (member Owner: string)(v)) 
   let registration = (^v: (member Registration: string)(v))
   {Registration = registration; Owner = owner}

let car = {Car.Registration = "xyz"; Owner = "xyz"; Wheels = 3; customAttribute1= "xyz"; customAttribute2 = "xyz"}
let truck = {Truck.Registration = "abc"; Owner = "abc"; Wheels = 12; customField5 = "abc"; customField6 = "abc"}
let bike = {Owner = "hell's angels"; Color = "black"}
someComplexFun car //val it : Vehicle = {Registration = "xyz";
                   //Owner = "xyz";}
someComplexFun truck //val it : Vehicle = {Registration = "abc";
                     //Owner = "abc";}
someComplexFun bike //error FS0001:

已定义Vehicle类型,但可以是任何类型.然后定义someConplexFun,可以采用具有OwnerRegistration的任何类型.它必须为inline,其类型签名为:

The Vehicle type is defined but it could be anything. Then someConplexFun is defined that can take any type, that has Owner and Registration. It has to be inline and its type signature is:

val内联someComplexFun:
v:^ v->车辆
当^ v:(成员get_Owner:^ v->字符串)和
^ v :(成员get_Registration:^ v->字符串)

val inline someComplexFun :
v: ^v -> Vehicle
when ^v : (member get_Owner : ^v -> string) and
^v : (member get_Registration : ^v -> string)

您可以传递具有OwnerRegistration字段的任何类型,它将返回Vehicle,但是您当然可以将其打印出来或返回一个元组,等等.对于Bike类型,由于它没有Registration,因此此功能将失败.

You can pass any type that has Owner and Registration fields, and it will return a Vehicle but of course you can just print it out or return a tuple, etc. For the Bike type, since it doesn't have Registration this function will fail.

这篇关于具有通用字段类型的多态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆