隐式转换:Scala对Extension Method的回应

.NET有Extension Methods。当你:

using System.Linq;

然后,你的所有数组对象神奇般地“拥有”了Contains, Count, GroupBy, OrderBy等一系列“前所未有”的方法。你感觉你的“Array”类被人注入了额外的东西。

C#的Extension Method定义为静态方法。如果第一个参数加上了this修饰符,那么这个方法就被认为是Extension Method。该方法被加在this修饰的参数的类型上。

注意ShyBoyKissSupport.Kiss方法

using System;

namespace BoyKiss
{
abstract class Child
{
public string name { get; set; }
protected Child(string name)
{
this.name = name;
}
}

class Boy : Child
{
public Boy(string name) : base(name) {}

public void Kiss(Girl girl)
{
System.Console.WriteLine("{0} kisses {1}", name, girl.name);
girl.OnKissed(this);
}
}

class Girl : Child
{
public Girl(string name) : base(name) {}

public void OnKissed(Child child)
{
System.Console.WriteLine("{0} is kissed by {1}", name, child.name);
}
}

class ShyBoy : Child
{
public ShyBoy(string name) : base(name) {}
// Kiss method is missing
}

static class ShyBoyKissSupport {
public static void kiss(this ShyBoy me, Girl girl)
{
System.Console.WriteLine("{0} bravely kisses {1}", me.name, girl.name);
girl.OnKissed(me);
}
}

class MainClass
{
public static void Main(string[] args)
{
var b = new Boy("Bob");
var g = new Girl("Alice");

b.Kiss(g);

var b2 = new ShyBoy("Peter");
var g2 = new Girl("Wendy");

b2.Kiss(g2);
}
}
}
/* 输出:
Bob kisses Alice
Alice is kissed by Bob
Peter bravely kisses Wendy
Wendy is kissed by Peter
*/


然后ShyBoy类就拥有了Kiss方法。

-----------------

下面讨论Scala语言。所涉及的问题域如下:

package boykiss

class Child(val name:String) {
}

class Boy(name:String) extends Child(name) {
def kiss(girl: Girl) {
println(name+" kisses "+girl.name);
girl.onKissed(this);
}
}

class Girl(name:String) extends Child(name) {
def onKissed(child : Child) {
println(name +" is kissed by " + child.name);
}
}

class ShyBoy(name:String) extends Child(name) {
// kiss method is missing.
}


注意到,这个ShyBoy类仍然没有kiss方法。我们需要一定的代码给他加上。

Scala没有Extension Method,但是有隐式类型转换。如果一个方法加上了implicit修饰符,那么它就认为是一个隐式转换方法。如下:

object ShyBoyKissSupport {
implicit def fromShyBoy(b : ShyBoy) = new ShyBoyWrapper(b);
}

class ShyBoyWrapper(me: ShyBoy) {
def kiss(girl: Girl) {
println(me.name+" bravely kisses "+girl.name);
girl.onKissed(me);
}
}

object定义了单例对象ShyBoyKissSupport。它的fromShyBoy方法有implicit修饰,因此会自动把ShyBoy对象用该方法转换成ShyBoyWrapper类的对象。

ShyBoyWrapper类只不过是一个封装器,封装了一个ShyBoy。它具有kiss方法。

主程序这样写:

import ShyBoyKissSupport.fromShyBoy

object Main {

def main(args : Array[String]) {
val b = new Boy("Bob");
val g = new Girl("Alice");

b.kiss(g);

val b2 = new ShyBoy("Peter");
val g2 = new Girl("Wendy");

b2.kiss(g2);
}

}
/* 输出:
Bob kisses Alice
Alice is kissed by Bob
Peter bravely kisses Wendy
Wendy is kissed by Peter
*/

这个import ShyBoyKissSupport.fromShyBoy在这里是必要的,否则在下面的代码中,这个隐式转换方法不可见,也就不能自动隐式转换。实际中还可以用package object完成这个工作。

当调用b2.kiss(g2)的时候,因为b2没有kiss方法,但有隐式转换函数fromShyBoy,而且ShyBoyWrapper有kiss方法。所以,b2会先被隐式转换成ShyBoyWrapper,然后调用ShyBoyWrapper.kiss方法。


总结:Scala的隐式转换可以完成类似Extension Method的功能。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值