Julia类和多重派发

类是编程语言基本抽象概念,比如实数、整数、字符串等等。一般分成静态和动态的,如果代码根据不同的类可以执行不同的操作,称为Polymorphism(多态的),动态语言一般都是是多态的。 Julia是动态类语言,不过也继承了静态类的高效性,如果不添加类型声明,则值是任意类,如果指定类,可以显著提高计算效率和稳定性。 Julia类型的特点也成为它高效的一个重要原因。Julia的类型系统不支持类似于Python/Cpp那样以对象的成员隐式继承,类之间的继承关系需要明确指定(据说继承了lisp的元编程特点,不过我不懂lisp)。

Julia中的所有实体类都是最终类,它们的父类只可能是抽象类。julia中的类都是面向对象的,只有执行类(run-time type)不存在编译类(compile-time type),只有value含有类型,变量只是值的名字。

Julia 对于不指定类执行默认类型,默认类型是任意类,这样我们就可以非常方便的定义函数。让绝大多数程序可以体会不到类的存在。

     f(x,y)=x^2+y^2

后续也可以对默认类型的函数追加声明类型,这样有三个好处:

  1. julia有极为强大的多重派发功能
  2. 增加可读性
  3. 便于发现程序错误

类的声明

类通过::进行声明,可以读作“is an instance of”

	function test()
		x::Int8 = 32
	end

	test()  #32
	typeof(ans) #Int8
	function sinc()::Float64
		if x==0
			return 1
		end
		return  in(pi*x)/(pi*x)
	end

可以将结果转化为Float64。

类的断言

	function sinc()::Float64
		if x==0
			return 1
		end
		return  in(pi*x)/(pi*x)
	end
	sinc(0)::Int8 #TypeError: typeassert: expected Int8, got Float64

或者用

	a=8
	isa(a,Int) #True

丰富的原始类型(位类型)

julia提供丰富的位类型体现专业的计算能力,如Int8 Int16 Int32 Int64 Int128,UInt8… Uint128,Float8…Float128

抽象类

	Int8  <: Signed # true

其中<: is a subtype of 用来确定是否子类。

组合类

组合类在不同语言中叫法不同,可能称为“records、structs、objects“等,在很多语言中组合类是唯一用户自定义类,在julia中也是最主要的用户自定义类型,在主流面向对象语言中,如c++、java、python中,function是和组合类耦和在一起的,构成“Objects”,在更纯粹的面相对象语言中,如ruby 和smalltalks,无论是不是组合类,值都是对象;在不是那么纯粹的面向对象语言中,如c++ 和Java中,integer 和浮点值不是对象,而用户定义的类是和方法一起构成对象的。在julia里,所有值都是都是对象,但是function并不和他们作用的对象绑定在一起。这也是多重派发的基础。

组合类通过struct开辟,

	struct Mystruct
		bax
		bay::Int8
		baz::Float64
	 end

通过类似于函数的方式可以组合类 的值

   foo = Mystruct("Hello", 64, 3.2)
   typeof(foo) #Mystruct

可以看组合类的列表

     fieldnames(Mystruct) # :bax, :bay, :baz

调用组合类

    foo.bax #"Hello"
    foo.bay #64

我们可以测试一下,再开辟一个值

	foo2 = Mystruct(66, 3, 5.5)
	foo2.bax # 66
	foo2.bay # 3
	foo2.baz # 5.5

可见对于未定义类bax,foo和foo2并不冲突。
Julia 的对象一经声明后,默认是不可更改的(immutable)。

可以通过

	mutable struct Bar
		bax
		bay::Float64
	end 
 bar = Bar("Hello", 3.5)
 bar.bay = 1//12

可以更改类。

总结

Julia不变类具有两个基本特点:

  1. 不变类不可更改
  2. 不变类具有免复制的特性,因为编译器并无法区分它本身和它的复本。

断言类型

上面说到的三种类型:抽象类,原始类,组合类,实际上是非常相关的,比如都是显式断言,含有名字,含有显式断言的父类,可能含有参数。 因此他们遵循相同的逻辑,这些类都属于同一类 DateType

	 typeof(Real) #DateType
	 typeof(Int)  #DateType

类的结合

通过关键字 Union 可以将不同的类结合

	 IntOrString = Union{Int, AbstractString}  #Union{ Int, AbstractString}
	"what" :: IntOrString  #"what"
	 1.0 :: IntOrString  #Error

类的参数化

对于固定类,如果想调节类型很困难,julia中提供了一个重要特性,就是参数化,所有声明类型(DataType)都可以参数化。

组合类参数化

	struct Point{T}
		arg::T
		lin::T
	end

这样做的好处,我们可以通过Point分别开辟不同的固定组合类

	point = Point(2.3,4.5) # Point{Float64}(2.3,4.5)
	point2 = Point{Int16}{3,4)

Point同样是一个有类型的对象,含有所有参数子类。

	Point{Float64} <: Point # True

抽象类参数化

抽象类参数化是相似的

abstract type Pointy{T} end
Pointy{Float64} <: Pointy #True

struct Point{T} <: Pointy{T}
	x::T
	y::T
end

元组类

元组和数组不同,元组不可更改,只可以插入和删除。
元组用( )开辟。

	typeof(("1",2,3)) #Tuple{String,Int64,Int64}

可变参数元组类

通过Vararg{T} 可以开辟0-任意个T类型元组。

mytype = Tuple{AbstractString,Vararg{Int}} #Tuple{AbstractString,Vararg{Int64,N} where N}
isa(("1",), mytupletype) #True

也可以用Vararg{Int,N} 开辟特定N个。例如

mytype = Tuple{AbstractString,Vararg{Int,3}} #Tuple{AbstractString,Int64,Int64,Int64}

UnionAll类

前面讲类的参数化时,有说到当对于有参数化的类,所有参数类都属于该类的子类,例如

	Type{Float64} <: Type #True

这里Type就相当于Union{ Type{T} where T} 也就是UnionAll类。例如Ptr可以更精确的写为Ptr{T} where T 表示所有可能的T组成的UnionAll类。

对于多参数情况,如Array{T,N} 可以固定一个,如Array{T, 1} where T代表所有的一维数组构成的类。

还可以固定范围,如

	Array{T} where T <: Real

对类的操作

由于类本身也是对象,此常规函数也可以做用在类上,比如<:函数就代表了类的包含关系。

 isa(1, Int) #True
 typeof(Int) #Datatype  type由于是object 仍然拥有type 
 typeof(Union{Real,String}) # Union
 typeof(Union) #dataType
 supertype(Float64) #AbstractFloat
 supertype(AbstractFloat) #Real
 supertype(Real) #Number
  supertype(Number) #Any

优化默认输出

我们经常有改变类输出风格的需求,这个可以通过重载show函数来完成,比如我给出一个表达复数的组合类,想以极坐标的形式输出

struct Polar{T <: Real} <:Number
    r::T
    θ::T
end

可以通过

Base.show(io::IO, z::Polar) = print(io, z.r, " * exp(", z.θ, "im)")
Polar(3.0,4.0) #3.0 * exp(4.0im)

得到。还可以增加文字说明

Base.show(io::IO, ::MIME"test/plain", z::Polar{T}) where{T} = print(io, "Polar {$T} complex number:\n   ", z)
Polar(3.0,4.0) # Polar{Float64} complex number:
                              3.0 * exp(4.0im)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值