inheritance - 实例化子类型之前的 Julia Subtyp 验证
问题描述
只要创建子类型而不是实例化时,我只需要在子类型结构上调用 validation_field() “此函数将验证子结构”。所以首先我如何在超类型中定义子类型(是否有任何基本函数,例如“getSubtype()”),朱莉娅中是否有任何“this”关键字,我的方法有什么替代方法吗?
function validate_field(field::Model1)
@assert typeof(attr)==float, "Validation error for type of default"
end
struct Model1
validate_field("this")
end
struct G <: Model1
atrr::float
end
解决方案
验证功能可以通过反射实现:
julia> function validate_field(::Type{T}) where {T<:Model1}
fieldtype(T, :attr) <: Float64 || error("`attr` has invalid field type")
end
validate_field (generic function with 2 methods)
julia> validate_field(G)
true
julia> struct H <: Model1
attr::Symbol
end
julia> validate_field(H)
ERROR: `attr` has invalid field type
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] validate_field(#unused#::Type{H})
@ Main ./REPL[10]:2
[3] top-level scope
@ REPL[13]:1
其余的不会从 Java 继承。首先,没有具体的继承。你只能有抽象超类型,它不能有字段:
abstract type Model1 end
然后,方法不与类型相关联,而是与函数相关联。构造函数也是如此;所以没有构造函数的继承,也没有this
.
您可以通过执行以下操作来大致满足您的要求:
julia> subtypes(Model1)
2-element Vector{Any}:
G
H
julia> foreach(validate_field, subtypes(Model1))
ERROR: `attr` has invalid field type
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] validate_field(#unused#::Type{H})
@ Main ./REPL[10]:2
[3] foreach(f::typeof(validate_field), itr::Vector{Any})
@ Base ./abstractarray.jl:2141
[4] top-level scope
@ REPL[15]:1
但这只会验证运行时某个特定点存在的一组未指定的子类型。
更朱利安的方法是在子对象的消费者中假装(通过鸭子打字)他们有一个与他们所做的任何事情兼容的类型的字段:Model1
attr
somefunction(m::Model1) = m.attr^2
将适用于存在适当方法的任何事物^
。如果这不起作用,MethodError
无论如何你都会得到一个,这并不比来自validate_field
.
可能您应该首先熟悉多重分派,以及 Julia 的面向对象的惯用替代方案,然后尝试以不同的方式设计您的方法。
如果你发疯了,你可以使用一种 trait:
julia> HasAttr(::Type{T}) where {T} = Val{false}()
HasAttr (generic function with 1 method)
julia> HasAttr(::Type{T}) where {T<:Model1} = Val{fieldtype(T, :attr) <: Float64}()
HasAttr (generic function with 2 methods)
julia> @code_warntype HasAttr(G)
Variables
#self#::Core.Const(HasAttr)
#unused#::Core.Const(G)
Body::Val{true}
1 ─ %1 = Main.fieldtype($(Expr(:static_parameter, 1)), :attr)::Core.Const(Float64)
│ %2 = (%1 <: Main.Float64)::Core.Const(true)
│ %3 = Core.apply_type(Main.Val, %2)::Core.Const(Val{true})
│ %4 = (%3)()::Core.Const(Val{true}())
└── return %4
julia> some_other_function(m) = some_other_function(m, HasAttr(typeof(m)))
some_other_function (generic function with 1 method)
julia> some_other_function(m, ::Val{true}) = missing
some_other_function (generic function with 2 methods)
julia> some_other_function(G(1.0))
missing
julia> some_other_function(H(:bla))
ERROR: MethodError: no method matching some_other_function(::H, ::Val{false})
Closest candidates are:
some_other_function(::Any) at REPL[23]:1
some_other_function(::Any, ::Val{true}) at REPL[24]:1
Stacktrace:
[1] some_other_function(m::H)
@ Main ./REPL[23]:1
[2] top-level scope
@ REPL[27]:1
但我可以告诉你,这不是你真正想要的......
推荐阅读
- reactjs - 如何使用 React 在 Stripe 中对已保存的卡进行收费?
- java - 将多张照片从服务器发送到客户端卡在一个while循环中
- python - macOS Bundle 从 shell 脚本调用 python
- javascript - 未找到命令但模块存在
- cobol - 如何绕过/跳过某些记录 COBOL?
- javascript - Vue.js 2 v-for 循环没有获取数组元素
- python - Xpath 问题,试图根据另一个元素的结果定位一个元素
- java - 我的视图 land_layout 无法正确定位点
- java - 在 RDBMS 中存储未知对象类型的列表?
- javascript - 如何制作只有 2 列的 Discord 嵌入