您的位置:首页 > 编程语言

part 8: comparison between OOL and FL

2017-05-25 14:51 316 查看
OOP和函数编程的区别
表格:行是operation,列是variant



函数编程:
     每个operation都是一个函数,每个函数都有若干branch,每个branch都对应一个variant
     定义datatype,每个variant都对应一个constructor
面向对象编程:
     定义一个基类,每个operation是一个类函数,基类中的函数是抽象的
     每个variant是一个子类,并且实现所有的抽象函数

问题一:如果有函数带有多种类型的参数?



函数编程:
    通过wildcard pattern + helper function + case语句
面向对象编程:
     Double Dispatch

Double Dispatch
将需要知道对方的类 转化成 调用对方的函数
第一次分配:variant类应该知道自己如何做一个operation=>如Int类型就应该调用arg.add_int(self)
第二次分配:对方的add_int知道应该如何将自己和int相加
调用栈:
     add(a, b)
     a.add_values(b)
     b.add_A的类型(a自己)
     b正确处理





Multiple Dispatch
每个add_values都有自己对应的参数类型,类里会有多个add_values
当调用a.add_values(b),将会在运行时挑选出A中接收B类型的参数的add_values, 直接调用
注意:Java和C++的static overloading虽然也能根据参数类型挑选对应函数,但是是编译期决定的,并不是运行时决定的。

多重继承:可能会在fields和methods上有冲突
     C++是支持多重继承的+abstract method
     Ruby运行有一个直接的基类和多个mixin
     Java支持一个直接的基类和实现多个接口

Mixin
类似接口,类能include mixin, 但是不能直接实例化mixin。
minxin不能有instancevariable
定义:module M … end
使用:class A < B
               include M
          end
Ruby自带的mixin: Enumerable(实现each方法)和Comparable(实现<=>方法)
     
Abstract method和high-order function的相同之处
     都可以先定义一个框架,由client实现其中的细节。
     Abstract method是通过override函数实现的
     High-order function是通过传入函数实现的

Polymorphism:
ML中:parametric polymorphism / generics
Ruby中:subtype polymorphism / subtyping
Generic和Subtyping:
     Generic适用于 可以是任何类型的参数,但必须是同一个类型 的情况
     Subtyping适用于 有extra fields的对象的代码重用 的情况
Bounded Polymorphism:
     Generic + Subtyping
     对于depth subtype如List,可以使用List<T extend A>,这样可以修改List的内容,替换成其他的T,但是注意,都是同类型的。

Subtyping:
     让一个类型{f1:t1, f2:t2...}也是类型{f2:t2…}。前者是subtype,subtype拥有更多的信息。
     t1 <: t2: t1是t2的subtype。
     如果e是t1,那么e也是t2。t2可以理解成父类,t1是子类,子类能拥有更多的field,且子类是基类
     任何使用t2的地方都可以使用t1(t1是t2,但是t2未必是t1)
     Depth subtyping:
          如果t1<:t2, 不能让 t3 : {f1:t1} <: t4 : {f1:t2} 
          原理:如果有函数将x.f1 = t2,那么就会造成t3.f1 = t2。但是如果通过t3.f1去取t1比t2多出来的fields就会报错。
                     当有赋值的时候,depth subtyping就会出现field丢失的情况
                     因此Java禁止赋值一个t1类型的数组内容为t2,但是允许depth subtyping
                     所有类型都可以看做是Null的subtype,所以Java中也会在运行时检查Null
      Function subtyping:不是如何调用函数,而是函数本身的委托
          如果 ta <: tb,则函数t->ta <: t->tb。能返回更多fields(promise more)的函数可以替换。return type: covariant(works the same way)
          如果 ta <: tb,则函数tb->t <: ta->t。需要更少fields(need less)的函数可以替换。argument type: contravariant(works the oposite way)
          除了self/this这个参数,由于实现问题必须是subtype,不能使contravariant的
     OOP中的subtype:
          因为field能够修改,所以subtype的field类型不能改变(原因参照depth subtyping)
          因为methods不能修改,所以subtype的methods能够使用supertype对应函数的subtype     
     Subclass和subtype不同:
          class:定义了对象的行为,子类通过继承并extend/override这些behavior
          type:定义了对象的类型和能够响应的消息,子类型是为了替换父类型并且防止发生错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程