`
Eastsun
  • 浏览: 304129 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

隐式转换:比动态类型更强大?

阅读更多
  本文内容主要来自Implicit Conversions: More Powerful than Dynamic Typing?,我只对其中一部分进行了翻译。
  隐式转换是[url=Haskell type classes]Scala[/url]中实现的一种类似于Haskell type classes的类型系统,它使得Scala这种静态类型的语言具有某些“动态”的特性。下面用具体例子来说明。

案例1给String添加一个reduce方法,其返回值为字符串中大写字母组成的新字符串。
在Scala中,最终效果如下:
//Scala
val acronym = "Microsoft Certified Systems Engineer".reduce
println(acronym)            // MCSE

  由于String是Java语言内置的类型,现在遇到的问题是:在静态语言中,我们不能在运行时往已经存在的类中动态添加方法。
  在Scala中,我们可以定义一个新的类型,使它具有所需要的方法,然后再顶一个一个从已有类型到新类型的隐式转换。然后Scala编译器将会在幕后实施其魔法。代码如下:
class MyStr(str:String) {
    def reduce = str.foldLeft(""){ (s,c) =>
                     if(c.isUpperCase) s+c else s
                 }
}

implicit def str2MyStr(str:String) = new MyStr(str)


作为对照,我们看看在Ruby中的实现:
class String
  def reduce
    arr = unpack('c*').select { |c| (65..90).include? c }
    arr.pack 'c*'
  end
end
 
puts 'HyperText Transfer Protocol'.reduce       # HTTP



案例2一个稍微复杂一点的问题:重载整数类型的<操作符,使得它能与String比较,并且但String的长度小于该整数时返回true,否则返回false
  在Scala中,同样可以通过隐式转换机制来解决该问题。这一次我们使用比上面更简洁的形式:
//Scala,that's all
implicit def lessThanOverload(i: Int) = new {
    def <(str: String) = str.length < i
}

  下面我们看看Ruby中如何解决这个问题,一个很自然的想法是玩Fixnum中添加所需的方法:
class Fixnum
  def <(str)
    str.size < self
  end
end

  很不幸的是,这个看起来很对的方法是行不通的。每次调用整数的<操作符时都会进入一个死循环并很快导致堆栈溢出。
  我们可以将方法改写成如下以避免这个问题:
class Fixnum
  def <(str)
    self >= str.size
  end
end

  这次不用担心堆栈溢出了,但新的问题出现了:
引用
irb(main):006:0> 123 < 'test'
=> true
irb(main):007:0> 123 < 123
=> true

  这个问题的最终Ruby解法是这样的:
class Fixnum
  alias_method :__old_less_than__, '<'.to_sym
  def <(target)
    if target.kind_of? String
      __old_less_than__ target.size
    else
      __old_less_than__ target
    end
  end
end

  囧,相比Scala,Ruby的解决方法显得即冗长且丑陋。
分享到:
评论
13 楼 Scriptlet 2008-10-08  
所有的动态方法都属于耍小聪明,貌似可以解决一些小问题,节约一点时间。但是在大型项目中全是噩梦-根本都不知道对象在运行态成了什么东西。
12 楼 smilerain 2008-09-17  
用个方法转换最直接. java多了个范型很不爽.
11 楼 ray_linn 2008-09-17  
zbm2001 写道
请移步:
http://www.cnblogs.com/allenlooplee/archive/2008/06/01/1211520.html

PS: 吸纳别人优秀的东西是件非常好的事情,但起码也得谦虚点。



教训人也得找点因头?你这句话简直是胡扯,我哪一句被您看出不谦虚了?
10 楼 liusong1111 2008-09-17  
Eastsun 写道
对于隐式转换,我这儿讲的只是它的两个比较简单的应用。
这里有几篇比较不错的文章:
scala学习笔记(5) -- implicit type
Scala Implicits: a dose of Magic


还有,这里还有个帖子:付出太多,得到太少 - 闲谈函数返回值
我在后面给出了个Scala的解决方法能够解决LZ提出的部分要求,但不知是没人看到还是我的解法不符合要求,没有人对此关心。


俺看到了,scala确实很优秀.
没有更多想法与大家讨论,于是就没回贴.

隐式转换,记得groovy也有类似的方案.

9 楼 Eastsun 2008-09-17  
对于隐式转换,我这儿讲的只是它的两个比较简单的应用。
这里有几篇比较不错的文章:
scala学习笔记(5) -- implicit type
Scala Implicits: a dose of Magic


还有,这里还有个帖子:付出太多,得到太少 - 闲谈函数返回值
我在后面给出了个Scala的解决方法能够解决LZ提出的部分要求,但不知是没人看到还是我的解法不符合要求,没有人对此关心。
8 楼 Eastsun 2008-09-17  
假设就和Date的Year比较吧,这样就可以了:
implicit def lessThanOverload(i: Int) = new {
    import java.util.Date
    def <(str: String) = str.length < i
    def <(date: Date)  = date.getYear < i
}
7 楼 QuakeWang 2008-09-17  
请教一个问题,对于需求2,如果还需要增加使得它能与时间类型比较,在Scala中应该如何写?是像这样?
implicit def lessThanOverload(i: Int) = new {
    def <(str: String) = str.length < i
    def <(date: Date) = date....
}
6 楼 zbm2001 2008-09-17  
请移步:
http://www.cnblogs.com/allenlooplee/archive/2008/06/01/1211520.html

PS: 吸纳别人优秀的东西是件非常好的事情,但起码也得谦虚点。
5 楼 ray_linn 2008-09-17  
回楼上:

C#却是静态的,你检查个类型给我看看?你再怎么着,你还得显式声明,C#却是自动的。
4 楼 zbm2001 2008-09-17  
ray_linn 写道
看看C#的,超级简单


public class StringFun{

  public static Reduce(this string str){

    //bala bala
  }
}

public class Demo{

public static void Main(String[] strs){
String str="Smaple String";
str.Reduce();}
}


这样就可以attach到任意一个String上(只要你引用它的namespace).

这个就别拿来说事了,活脱脱模仿javascript原型继承,调用原型的方法
3 楼 ray_linn 2008-09-17  
看看C#的,超级简单


public static class Fun{
        public static string Reduce(this string str){

            var res = (from c in str.ToCharArray() where Char.IsUpper(c) select c).ToArray<char>();
            return new string(res);

        }
    }


这样就可以attach到任意一个String上(只要你引用它的namespace).
2 楼 Eastsun 2008-09-16  
但这些缺点动态语言不同样存在么?
1 楼 hax 2008-09-16  
隐式转换也存在问题,它降低了代码的直观性。后面那个例子尤其如此——运算符重载所具有的缺点,隐式转换也同样有。

相关推荐

    Scala程序设计(第2版)

    第2章 更简洁,更强大 28 2.1 分号 28 2.2 变量声明 29 2.3 Range 31 2.4 偏函数 32 2.5 方法声明 33 2.5.1 方法默认值和命名参数列表 33 2.5.2 方法具有多个参数列表 34 2.5.3 Future简介...

    medusa:试图像Medusa一样使Python更强大,更快速!

    美杜莎 试图像Medusa一样使Python更强大,更快速! Python是一种解释型语言,它有其优点和缺点,其目的是... 诸如ShedSkin项目之类的许多项目尝试将隐式类型的Python转换为C ++,但都对输入的Python代码施加了某些限制

    Xtend官方文档-第一章-入门

    Xtend 是一种静态类型的编程语言,...强大的开关表达式 - 隐式的类型转换 多重调度 - 又名:多态方法调用 模板表达式 - 具有智能空白处理 没有语句 - 一切都是表达 属性 - 简化了 getter 和 setter 的访问。。。。。

    Cyjb:我的 C# 基础类库

    完整的类型转换解决方案:支持隐式、显式和自定义类型转换。支持 接口,能够直接用在泛型类型中。能够动态添加额外的类型转换。能够在 IL 中使用类型转换功能。对反射的高级支持:更强大的类型成员查找。很容

    整理后java开发全套达内学习笔记(含练习)

    自动类型提升又称作隐式类型转换。 强制类型转换:int ti; (byte) ti ; 强制转换,丢弃高位 宣告变量名称的同时,加上“final”关键词来限定,这个变量一但指定了值,就不可以再改变它的值 如:final int n1=...

    SM3算法在用Fortran实现的案例

    4. **静态类型**:Fortran 是一种静态类型的语言,变量必须在声明时指定数据类型,并且不允许隐式类型转换。 5. **流程控制**:Fortran 支持循环结构、条件语句和子程序(类似于函数),以及模块化编程的概念,有助...

    Microsoft SQL Server 2005技术内幕: T-SQ程序设计.pdf

     1.4 隐式转换(Implicit Conversion)  标量表达式  筛选表达式  1.5 基于CLR的用户定义类型  UDT理论简介  开发UDT  1.6 XML数据类型  关系数据库中的XML支持  什么时候应该使用XML代替关系表现形式?  ...

    Swifter-Swift 开发者必备 Tips (第四版).zip

    然后为了简便起见,我们再添加一个将字符串转换为 NSRegularExpression 的操作符 (当然也可以使用 StringLiteralConvertible,但是它不是这个 tip 的主题,在此就先不使用它了): prefix operator ~/ prefix ...

    tsql.tech-Code-snippets:我使用和_或已创建的适用于DBA或SQL开发人员的有用SQL Server脚本SP

    可用性组信息查找活动锁在计划缓存中查找密钥查找在PlanCache中查找长期运行的查询在PlanCache中查找最昂贵的查询在PlanCache中查找查询的计划在PlanCache中查找隐式转换查询在一段时间内测量IO延迟和吞吐量索引使用...

    vue语法.rar

    它不能与其他的值进行运算,没有隐式转换 5.它的值可以被转换成布尔值或字符串,不能转换成数字 十八、set数据结构 set数据结构,类似数组,所有的数据都是唯一的,没有重复的值。它本身是一个构造函数 size...

    C语言入门经典(第4版)--源代码及课后练习答案

    2.12.1 自动转换类型 53 2.12.2 隐式类型转换的规则 54 2.12.3 赋值语句中的隐式类型转换 54 2.13 再谈数值数据类型 55 2.13.1 字符类型 56 2.13.2 字符的输入输出 57 2.13.3 宽字符类型 60 2.13.4 枚举 60 ...

    java8集合源码-how-to-prepare-for-1Z0-808-certification:如何准备1Z0-808认证

    您将学习(或强化)语言的基础知识,如变量、数据类型、数组、循环、类、方法、异常以及一些不那么基础的主题,如隐式缩小、显式转换、自动装箱、嵌套类、多态和继承、抽象类和接口,以及一些处理集合、字符串和日历...

    C# Winform数据库应用设计(附开发案例

    331隐式转换 74 332显式转换.…… 74 333常用类型转换方法… 7 任务实训部分 77 1:方法的使用 2:从邮件地址提取用广名 80 3:网址类型分析 81 4:字符串转换 82 巩固练习. 84 第4章指导学习:阶段总结 86 知识总结 翻着...

    PLSQLDeveloper下载

     PL/SQL主要用于数据库编程,所以其所有的数据类型跟Oracle数据库里的字段类型是一一对应的,大体分为数字型、布尔型、字符型和日期型。这里简单介绍两种常用数据类型:number、varchar2。 number 用来存储整数和...

    PL/SQL Developer8.04官网程序_keygen_汉化

    该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。 命令窗口  使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同的感观,另外还增加了一个内置的带语法加强特性的脚本编辑器。这样...

    C#微软培训资料

    6.1 隐式类型转换 .48 6.2 显式类型转换 .53 6.3 小 结 .56 第七章 表 达 式 .58 7.1 操 作 符 .58 7.2 算术操作符和算术表达式.59 7.3 赋值操作符和赋值表达式.64 7.4 关系操作符和关系表达式.65 ...

    JBPM4工作流应用开始指南.rar

    第二篇主要涉及基于jBPM4这个强大的应用程序框架打造属于自己独特业务的“企业流程管理平台”,包括jBPM4扩展研发先决条件、深入jPDL和jBPM Service API、升级jBPM3到jBPM4、流程虚拟机原理、jBPM4的设计思想、随需...

Global site tag (gtag.js) - Google Analytics