提问人:ahm5 提问时间:8/25/2021 最后编辑:ahm5 更新时间:8/25/2021 访问量:172
实例化子类型之前的 Julia 子类型验证
Julia Subtyp validation before the Subtype is instantiated
问:
我只需要在创建子类型时而不是在实例化时在子类型结构上调用 validation_field() “此函数将验证子结构”。所以首先我如何在超类型中定义子类型(是否有任何基本函数,例如“getSubtype()”),julia 中是否有任何“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
答:
4赞
phipsgabler
8/25/2021
#1
验证功能可以通过反射来实现:
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 对面向对象的惯用替代方法,然后尝试以不同的方式设计你的方法。
如果你发疯了,你可以使用一种特质:
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
但我已经可以告诉你,这不是你真正想要的......
评论
Model1
G <: Model1
G
fieldnames
getfield