实例化子类型之前的 Julia 子类型验证

Julia Subtyp validation before the Subtype is instantiated

提问人:ahm5 提问时间:8/25/2021 最后编辑:ahm5 更新时间:8/25/2021 访问量:172

问:

我只需要在创建子类型时而不是在实例化时在子类型结构上调用 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
继承 茱莉亚 这个 亲子

评论

0赞 phipsgabler 8/25/2021
因此,您的问题是“如何以编程方式确保所有子类型都只有浮点字段”?Model1
0赞 phipsgabler 8/25/2021
另外,请注意,您使用的术语和概念在 Julia 中不存在。没有具体的继承;“创建”和“实例化”之间没有概念或区别。
0赞 ahm5 8/25/2021
杰普,你是完全正确的。我可能会使用一些在茱莉亚中不存在的概念。但我有点迷失了我的approche。因为我想做的是,只要确保所有子类型在我子类型化时都具有 Float 类型的 attr(例如,在 Java 中创建子类型时),以及如何在超类型中定义子类型
1赞 DNF 8/25/2021
您应该知道,您不能对具体类型进行子类型化,因此不可能有 .的超类型必须是抽象的。如果需要对结构中的字段进行操作,可以使用 and 函数。但我怀疑你正试图以一种非最佳的方式解决你的问题。你能描述一下你更大的目标吗?G <: Model1Gfieldnamesgetfield

答:

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

但这只会验证在运行时的某个特定点存在的一组未指定的子类型。

更朱利安的方法只是在子对象的使用者中假装(通过鸭子类型)他们有一个与他们所做的任何事情兼容的类型字段:Model1attr

somefunction(m::Model1) = m.attr^2

将适用于存在适当方法的任何内容。如果这不起作用,你会得到一个无论如何,这并不比 的错误差。^MethodErrorvalidate_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

但我已经可以告诉你,这不是你真正想要的......