part 8: comparison between OOL and FL
2017-05-25 14:51
369 查看
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:定义了对象的类型和能够响应的消息,子类型是为了替换父类型并且防止发生错误。
表格:行是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:定义了对象的类型和能够响应的消息,子类型是为了替换父类型并且防止发生错误。
相关文章推荐
- [dynamic FL]part 6:comparison between Dynamic and Static
- A Comparison between Focus-Group and In-Depth Interview
- A High Level Comparison Between Oracle and SQL Server - Part II
- The Similarities and Differences Between C# and Java -- Part 1(译)
- A Technical Comparison between PDF and DJVU
- Comparison between the simplex algorithm and interior point method
- A Technical Comparison between PDF and DJVU
- [Error] ISO C++ forbids comparison between pointer and integer [-fpermiss
- A comparison between lcc-win32, gcc, and Intel's icl compiler
- CSharp - Comparison between IComparer and IComparable
- JNI - Divide by Zero. A comparison between Java and C(1)
- A Comparison Between Haar Wavelet Transform and Fast Fourier Transform in Analyzing Financial Time S
- Part 59 to 60 Difference between Convert ToString and ToString,String and StringBuilder
- Comparison between Hive, Impala, Drill and SparkSQL
- Comparison Modeling between Excel and PowerPivot
- Part 37 Difference between $scope and $rootScope
- The Similarities and Differences Between C# and Java -- Part 1(译)
- Difference Between == and === : A Simple Comparison
- Comparison Between NetCDF and HDF5
- comparison between distinct pointer types 'QPushButton*' and 'QAbstractButton*' lacks a cast