mixin 模拟多继承

转自:http://www.javaeye.com/subject/dlang
D1.0 代码
  1. /** TupleMixin 演示程序, DMD2.007/GDC0.24 测试通过
  2. Written in the D programming language 1.0
  3. 作者: oldrev
  4. Copyrights: BSD
  5. */
  6. import std.stdio;
  7. //PredT 参数的作用是让你能够在每个模板混入之前对它进行处理,
  8. //比如可以在混入前用 static assert 检查是否有特定的成员
  9. //总而言之,PredT 给你机会控制混入时的细节。
  10. template MixinTuple(alias PredT, L...)
  11. {
  12. mixin PredT!(L[0]);
  13. static if(L.length > 1)
  14. mixin MixinTuple!(PredT, L[1..$]);
  15. }
  16. // P 是所有准备当做超类的模板
  17. class Mixinable(SuperClass, P...) : SuperClass
  18. {
  19. private const string InitCode = "private void initAllMixins() {";
  20. //PredT 的一个例子,混入且产生与模板同名的 alias
  21. template MixinWithAliasPred(alias X) {
  22. mixin("mixin X!() " ~ (X.stringof)[0..$-2] ~ ";"); //去掉模板名称后的 '()'
  23. }
  24. mixin MixinTuple!(MixinWithAliasPred, P);
  25. private template MakeInitCode(TL...)
  26. {
  27. static if(TL.length == 0)
  28. const string MakeInitCode = "";
  29. else
  30. { //"HasMember" 惯用法
  31. static if(is(typeof(mixin(TL[0].stringof[0..$-2] ~ "._ctor"))))
  32. { //如果TL[0] 有 _ctor 成员函数(也就是 this()),我们就产生调用 _ctor 的代码。
  33. const string MakeInitCode = TL[0].stringof[0..$-2] ~ "._ctor();/n" ~
  34. MakeInitCode!(TL[1..$]);
  35. }
  36. else //没有 _ctor,继续递归
  37. const string MakeInitCode = MakeInitCode!(TL[1..$]);
  38. }
  39. }
  40. protected this()
  41. {
  42. mixin(MakeInitCode!(P)); //产生并执行代码调用所有模板的 this()
  43. }
  44. }
  45. /////////////////////////////////////////////////////
  46. //开始演示:
  47. /////////////////////////////////////////////////////
  48. template Policy()
  49. {
  50. this() {
  51. writefln("Policy.this()");
  52. }
  53. ~this() {
  54. writefln("Policy.~this()");
  55. }
  56. void bar(T)(T x) {
  57. writefln("bar()");
  58. }
  59. }
  60. template Policy2()
  61. {
  62. this() {
  63. writefln("Policy2.this()");
  64. }
  65. ~this() {
  66. writefln("Policy2.~this()");
  67. }
  68. void foo() { writefln("Policy2.foo"); }
  69. }
  70. class SuperBar //超类,或者叫基类
  71. {
  72. this() {
  73. writefln("SuperBar.this()");
  74. }
  75. }
  76. // Mixinable 用法演示——模拟多继承
  77. // Foo 类是组合 Policy, Policy2 和 基类 SuperBar 的结果
  78. class Foo : Mixinable!(SuperBar, Policy, Policy2)
  79. {
  80. this() {
  81. writefln("Foo.this()");
  82. }
  83. void foo() { writefln("Foo.foo"); }
  84. ~this() {
  85. writefln("Foo.~this()");
  86. }
  87. }
  88. void main()
  89. {
  90. Foo f = new Foo;
  91. f.foo;
  92. f.bar(3);
  93. }

输出:
  1. SuperBar.this()
  2. SuperBar.this()
  3. Policy.this()
  4. SuperBar.this()
  5. Policy2.this()
  6. Foo.this()
  7. Foo.foo
  8. bar()
  9. Foo.~this()
  10. Policy2.~this()
  11. Policy.~this()
 
<think>嗯,用户现在问的是接口是否允许多继承。我需要先回顾一下接口和多继承的相关知识。 首先,用户之前已经了解了多继承的概念以及它可能带来的问题,比如钻石问题和命名冲突。现在他们可能是在进一步探索不同语言如何处理这些问题,特别是接口的作用。 接口在编程中通常用于定义方法签名而不提供实现,这样可以实现多继承的一些好处,同时避免问题。比如在Java中,不能多继承,但可以实现多个接口。这可能就是用户想确认的:接口是否允许多继承。 接下来要确定不同语言对接口多继承的支持情况。比如Java的接口是允许多继承的,一个可以实现多个接口,而C#也似。但像C++,虽然支持多继承,但接口(通过抽象模拟)可能也有不同的处理方式。 用户可能想知道接口多继承是否解决了传统多继承的问题。需要指出接口因为没有状态,所以不会导致钻石问题中的状态冲突,但方法签名的冲突仍然可能存在,不过处理起来更简单,因为实现必须明确提供方法实现。 另外,用户可能混淆了接口继承和继承,需要明确说明接口的多继承多继承的区别。比如接口允许多继承,而在多数语言中不允许,但有些语言如Python允许多继承,这可能让用户产生疑问。 还要考虑用户可能的后续问题,比如接口多继承的实际应用场景,或者不同语言的具体语法如何处理接口的多继承。比如在Java中,用逗号分隔多个接口,而在C#中似。 需要确保回答准确,结构清晰,分点说明不同语言的情况,并举例说明。同时,要联系用户之前的问题,比如钻石问题在接口多继承中的情况,是否还存在问题。 最后,检查是否有遗漏的语言或特殊情况,比如TypeScript对接口多继承的支持,或者其他语言如Go通过接口隐式实现等方式的不同处理方式。</think>在大多数支持接口(Interface)的编程语言中,**接口通常是允许多继承的**。接口的多继承多继承有本质区别,因为它仅涉及方法签名的组合(而非具体实现或状态的继承),因此避免了传统多继承的复杂性问题。 --- ### **关键说明** 1. **接口的特性** 接口仅定义方法签名(或抽象方法),不包含具体实现或成员变量。因此: - 没有**状态冲突**(因接口无变量)。 - 即使多个接口有同名方法,实现只需**提供一个统一实现**即可解决冲突(例如Java要求显式覆盖)。 2. **主流语言的支持** - **Java**:支持接口多继承。例如: ```java interface A { void foo(); } interface B { void foo(); } class C implements A, B { public void foo() { ... } // 必须实现一个统一的foo() } ``` - **C#**:支持接口多继承,规则与Java似。 - **TypeScript**:接口允许多继承,且可合并不同接口的属性和方法。 3. **与多继承的对比** 多继承容易导致状态和方法实现的冲突(如“钻石问题”),而接口多继承仅需处理**方法签名冲突**,实现需自行解决这一问题。 --- ### **特殊语言案例** - **Python**:通过“混入”(Mixin模拟接口多继承,但本质上仍是多继承。 - **Go**:通过隐式接口实现(无需显式声明),天然支持多继承,但接口间不能有冲突方法。 --- ### **总结** 接口的多继承是广泛允许且安全的,因为它通过以下方式规避传统多继承的问题: 1. **无状态继承**:避免变量冲突。 2. **强制显式实现**:解决同名方法歧义。 3. **解耦行为定义**:接口仅描述“能做什么”,而非“如何做”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值