【发布时间】:2010-12-19 12:38:23
【问题描述】:
我希望这个问题不要被认为太主观 - 我真的不期待一个明确的答案,但我希望每个人的意见至少能帮助我形成自己的意见。
我正在实现一个自定义类型系统,它是经典 OOP 类型系统的超集。在这种类型系统中,对象实例可以在运行时组合以形成新实例,同时保留个体身份。
这段代码:
var p = new Person();
var pa = new Partner(p);
...产生单个组合对象,其中“p”和“pa”是不同的符合 OOP 的视图。 IOW,更改其中一个视图的属性值会立即反映在也包含此属性的任何其他视图上。
这一切都很好,但它缺少两个用于查询类型标识的关键 API。我真的很想能够写出这样的代码:
if (p is Partner)
{
(p as Partner).SomePartnerProperty = "...";
}
这当然行不通,因为“is”和“as”运算符的行为不能重载/扩展超出 .NET 的 OOP 规则规定的范围。尽管如此,我的类型系统中仍然需要这个功能。
我的第一个想法是使用可以附加到我的类型系统的所有实例的通用扩展方法:
public static bool Is<T>(this BaseType target) where T : BaseType { ... }
public static T As<T>(this BaseType target) where T : BaseType { ... }
忽略不区分大小写语言中的名称冲突问题,就功能而言,这似乎还可以:
if (p.Is<Partner>())
{
p.As<Partner>().SomePartnerProperty = "...";
}
但是,我不禁想知道 - 这真的是人们能想到的最好、最方便的 API 吗?
您如何建议我实现这两个运算符,以使它们在应用程序代码中使用起来很自然?
更新:对于任何想知道这种类型系统的目的的人......基本上,每种类型都属于以下两个类别之一:Identity 或 角色。在我上面给出的示例中,Person 是一个身份(设计上),而 Partner 是一个角色(同样,设计上 - 它可能设计不同)。这种类型系统的基本规则是任意数量的角色可以由任何给定的身份组成,而身份本身只能由更高的身份组成(例如,一个人可以成为联系人,但永远不能成为公司)。这种类型的系统使应用程序能够透明地处理例如合作伙伴对象,无论他们拥有什么身份(例如个人、公司、银行等)。
【问题讨论】:
-
在这里野刺,但我想知道你是否可以在 IronPython 中比在 C# 中更容易地做到这一点?您仍然可以在 C# 中编写一堆代码,只需在必要时使用 IronPython。也许了解 OO Python 的人可以加入。
-
这可以被描述为每个实例(而不是每个类型)的继承吗?此外,当您应用
pa特定值时,底层p对象会发生什么情况? -
如果你想让你的库成功,你不能忽略不区分大小写的语言——但好消息是不区分大小写的语言(至少是 VB!)可以工作这样的代码非常好,即使
Is和As是这里的保留字。上下文(即作为方法)使这种用法变得可行。 -
是的——Python 和 Ruby 都可以实现 mixin 策略。在 Iron* 变体中,如果每个 mixin 都实现了一个实际的 C# 接口,您应该能够将组合对象作为接口的实例公开回 C# 层。
-
@Blixt:可以。不过,我宁愿说组合,因为这里没有真正的“继承”,至少在 OOP 意义上不是。至于你的问题...... p 并不是 pa 的真正基础对象。它们都只是隐藏在场景后面的第三个复合对象的视图。在这方面, p 和 pa 自己不保存 任何 数据 - 它们的属性将所有内容委托给隐藏对象。如果有人说“如果(a == pa)”,答案将是“真”。
标签: c# .net type-systems