方法重载 #
一、方法重载概念 #
1.1 什么是方法重载 #
为已存在的函数添加新方法,使其支持新的类型:
julia
struct Point
x::Float64
y::Float64
end
Base.:+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y)
Point(1.0, 2.0) + Point(3.0, 4.0)
1.2 扩展标准库函数 #
julia
import Base: show, length
struct MyVector
data::Vector{Int}
end
length(v::MyVector) = length(v.data)
show(io::IO, v::MyVector) = print(io, "MyVector($(v.data))")
v = MyVector([1, 2, 3])
length(v)
二、运算符重载 #
2.1 算术运算符 #
julia
import Base: +, -, *, /
struct Point
x::Float64
y::Float64
end
+(p1::Point, p2::Point) = Point(p1.x + p2.x, p1.y + p2.y)
-(p1::Point, p2::Point) = Point(p1.x - p2.x, p1.y - p2.y)
*(p::Point, s::Real) = Point(p.x * s, p.y * s)
*(s::Real, p::Point) = Point(p.x * s, p.y * s)
/(p::Point, s::Real) = Point(p.x / s, p.y / s)
Point(1.0, 2.0) + Point(3.0, 4.0)
Point(1.0, 2.0) * 2
2 * Point(1.0, 2.0)
2.2 比较运算符 #
julia
import Base: ==, <, isless
struct Person
name::String
age::Int
end
==(p1::Person, p2::Person) = p1.name == p2.name && p1.age == p2.age
<(p1::Person, p2::Person) = p1.age < p2.age
isless(p1::Person, p2::Person) = p1.age < p2.age
Person("Alice", 25) == Person("Alice", 25)
Person("Alice", 25) < Person("Bob", 30)
2.3 索引运算符 #
julia
import Base: getindex, setindex!, length
struct MyArray
data::Vector{Int}
end
getindex(arr::MyArray, i::Int) = arr.data[i]
setindex!(arr::MyArray, val, i::Int) = (arr.data[i] = val)
length(arr::MyArray) = length(arr.data)
arr = MyArray([1, 2, 3, 4, 5])
arr[1]
arr[1] = 10
length(arr)
三、常用重载函数 #
3.1 show #
自定义显示格式:
julia
import Base: show
struct Point
x::Float64
y::Float64
end
show(io::IO, p::Point) = print(io, "Point($(p.x), $(p.y))")
show(io::IO, ::MIME"text/plain", p::Point) = print(io, "Point with coordinates ($(p.x), $(p.y))")
Point(1.0, 2.0)
3.2 convert #
类型转换:
julia
import Base: convert
struct MyInt
value::Int
end
convert(::Type{Int}, x::MyInt) = x.value
convert(::Type{MyInt}, x::Int) = MyInt(x)
Int(MyInt(10))
MyInt(10)
3.3 promote #
类型提升:
julia
import Base: promote_rule
struct MyFloat
value::Float64
end
promote_rule(::Type{MyFloat}, ::Type{Int}) = MyFloat
promote(MyFloat(1.0), 2)
3.4 iterate #
迭代支持:
julia
import Base: iterate, length
struct Countdown
start::Int
end
iterate(c::Countdown) = c.start > 0 ? (c.start, c.start - 1) : nothing
iterate(c::Countdown, state) = state > 0 ? (state, state - 1) : nothing
length(c::Countdown) = c.start
for i in Countdown(5)
println(i)
end
四、实践练习 #
4.1 练习1:复数类型 #
julia
import Base: +, -, *, /, abs, show
struct MyComplex
real::Float64
imag::Float64
end
+(a::MyComplex, b::MyComplex) = MyComplex(a.real + b.real, a.imag + b.imag)
-(a::MyComplex, b::MyComplex) = MyComplex(a.real - b.real, a.imag - b.imag)
*(a::MyComplex, b::MyComplex) = MyComplex(
a.real * b.real - a.imag * b.imag,
a.real * b.imag + a.imag * b.real
)
abs(c::MyComplex) = sqrt(c.real^2 + c.imag^2)
show(io::IO, c::MyComplex) = print(io, "$(c.real) + $(c.imag)im")
c1 = MyComplex(1, 2)
c2 = MyComplex(3, 4)
c1 + c2
c1 * c2
abs(c1)
4.2 练习2:分数类型 #
julia
import Base: +, -, *, /, ==, show, convert
struct Fraction
numerator::Int
denominator::Int
function Fraction(n::Int, d::Int)
d == 0 && error("Denominator cannot be zero")
g = gcd(n, d)
new(n ÷ g, d ÷ g)
end
end
+(a::Fraction, b::Fraction) = Fraction(a.numerator * b.denominator + b.numerator * a.denominator, a.denominator * b.denominator)
-(a::Fraction, b::Fraction) = Fraction(a.numerator * b.denominator - b.numerator * a.denominator, a.denominator * b.denominator)
*(a::Fraction, b::Fraction) = Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
/(a::Fraction, b::Fraction) = Fraction(a.numerator * b.denominator, a.denominator * b.numerator)
==(a::Fraction, b::Fraction) = a.numerator == b.numerator && a.denominator == b.denominator
show(io::IO, f::Fraction) = print(io, "$(f.numerator)/$(f.denominator)")
convert(::Type{Float64}, f::Fraction) = f.numerator / f.denominator
Fraction(1, 2) + Fraction(1, 3)
Fraction(1, 2) * Fraction(2, 3)
Float64(Fraction(1, 3))
4.3 练习3:向量类型 #
julia
import Base: +, -, *, /, dot, norm, show
struct Vec3
x::Float64
y::Float64
z::Float64
end
+(a::Vec3, b::Vec3) = Vec3(a.x + b.x, a.y + b.y, a.z + b.z)
-(a::Vec3, b::Vec3) = Vec3(a.x - b.x, a.y - b.y, a.z - b.z)
*(v::Vec3, s::Real) = Vec3(v.x * s, v.y * s, v.z * s)
*(s::Real, v::Vec3) = v * s
/(v::Vec3, s::Real) = Vec3(v.x / s, v.y / s, v.z / s)
dot(a::Vec3, b::Vec3) = a.x * b.x + a.y * b.y + a.z * b.z
norm(v::Vec3) = sqrt(dot(v, v))
show(io::IO, v::Vec3) = print(io, "Vec3($(v.x), $(v.y), $(v.z))")
v1 = Vec3(1, 2, 3)
v2 = Vec3(4, 5, 6)
v1 + v2
dot(v1, v2)
norm(v1)
五、总结 #
本章我们学习了:
- 方法重载概念:为已有函数添加新方法
- 运算符重载:自定义类型的运算符行为
- 常用重载函数:show、convert、promote、iterate
- 实践应用:复数、分数、向量类型
接下来让我们学习Julia的模块系统!
最后更新:2026-03-27