首页 > 代码库 > 9.4.2 实现接口和类型转换

9.4.2 实现接口和类型转换

9.4.2 实现接口和类型转换

 

我们已经讨论过在 F# 中如何声明接口,如何使用对象表达式,创建实现接口的值。这是一个非常轻量级的解决方案,类似于 lambda 函数。正如 lambda 语法,对于创建函数来说,并不总是合适的选择一样,有时,在命名类中实现接口,是有道理的。

我们将继续使用在本章前面的示例,来看一下用 C# 和 F# 实现接口,我们回顾一下两种语言中的接口声明:

 

// C# interface declaration 

interface IClientTest { 

  bool Check(Client client); 

  void Report(Client client); 

}

// F# Interface declaration 

type ClientTest = 

  abstract Check : Client –>bool 

  abstract Report : Client –> unit

 

接口有两个方法:一个检查客户,另一个把报告输出到屏幕。假设我们要实现接口,使用几个属性计算系数。早些时候,我们使用对象表达式创建了类似的检查,但是,当代码变得更加复杂时,把它移动到单独的类声明,或成为单独的源文件,会更好一些。

清单 9.17 显示了用 C# 实现的检查客户的收入和工作年限,使用了权重和阈值,所有这些都在构造函数中指定。类使用显式接口实现(explicit interface implementation),稍有点不寻常,但我们要等到讨论用 F#实现时,才会知道为什么。

 

清单 9.17 使用显式接口实现的客户检查 (C#)

class CoefficientTest : IClientTest {   <-- 实现 IClientTest

  readonly double incomeCoeff,yearsCoeff, minValue;

 

public CoefficientTest(double ic, doubleyc, double min) {   | 把参数值保存在

  this.incomeCoeff = ic;                              | 私有字段中

  this.yearsCoeff = yc;                                |

  this.minValue = http://www.mamicode.com/min; |

public void PrintInfo() { 

  Console.WriteLine("income * {0}+ years * {1} >= {2}", 

    incomeCoeff, yearsCoeff,minValue); 

bool IClientTest.Check(Client client){                       |

  return client.Income * incomeCoeff+                     | [1]

    client.YearsInJob *yearsCoeff < min;                    | 实现接口方法

}                                                    |

void IClientTest.Report(Client client){                      |

  Console.Write("Coeffficient {1}less than {0} ", minValue,    |

    client.Income *incomeCoeff + cl.YearsInJob * yearsCoeff);   |

  }                                                 |

}

 

要在 C# 中使用明确的语法实现接口成员,我们在写方法时[1],要包括接口的名字,并去掉访问修饰符。这只是一个微小的变化,而更重要的区别是如何使用类。接口中的方法(在这里,是Test 和 Report),在使用类时,不能直接访问;为了调用它们,首先要把类转换成接口类型。我们看一个例子:

 

var test = new CoefficientTest(0.001, 5.0,50.0); 

test.PrintInfo();

 

var cltest = (IClientTest)test; 

if (cltest.Check(john))cltest.Report(john);

 

我们不能简单地写成 test.Check(john),因为 Check 不是直接作为类的公共方法,只能作为接口的成员使用,因此,可以使用 cltest 值来访问,它的类型为 IClientTest。我们在代码中用明确的类型转换,和 var 关键字,因为这能帮助我们理解,在 F# 中接口实现是如何工作的。另一种选择是把变量类型声明成 IClientTest,然后,把值 test 赋给它,因为C# 编译器将它隐式转换为接口类型。

除了使用显式接口实现以外,类是完全不值一提;我们将使用它来对比 F# 代码。说到这......

9.4.2 实现接口和类型转换