具有通用字段类型的多态 [英] polymorphism with types for common fields
问题描述
这个问题是否可以通过惯用功能方法解决,泛型或歧视工会会是答案吗?
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
,可以采用具有Owner
和Registration
的任何类型.它必须为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)
您可以传递具有Owner
和Registration
字段的任何类型,它将返回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屋!