如何仅使用结构中的一个属性作为默认属性?

发布于 2025-01-14 17:43:18 字数 506 浏览 3 评论 0原文

我想创建一个具有许多属性的结构,但在应用函数时,我希望它的行为就像其类型是选定的属性之一,例如:

mutable struct Field{T}
    field_type::T
    field_description::String
end

如果我为它分配一个String,在执行 print(Field{String}("Hello", "World")) 时,如果字段类型是 Int8,我希望它打印 Hello 我希望能够做到Field{Int8}(1, "First term") + Field{Int8}(1,"Second term") 并得到 2 等等。这有可能吗?

对于更多上下文,我希望将一些元数据添加到字段类型,但它必须表现为所选的 field_type

I want to create a struct with many properties, but when applying the functions, I want it to behave like its type is one of the selected properties, for example:

mutable struct Field{T}
    field_type::T
    field_description::String
end

I want this struct to behave as the T type, if I assign it a String, when doing print(Field{String}("Hello", "World")) I want it to print Hello, if field type is a Int8 I want to be able to do Field{Int8}(1, "First term") + Field{Int8}(1,"Second term") and get 2 and so on. Is this possible somehow?

For more context, I want this to add some metadata to the Field Type, but it has to behave as the chosen field_type

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把人绕傻吧 2025-01-21 17:43:18

你把事情搞得太复杂了。您只需要认识到 Field{String}Field{Int8} 是两种不同的类型,并将它们视为不同的类型。

例如:

foo(f::Field{String}) = do_something()
foo(f::Field{Int8}) = do_something_else()

因此,对于打印和添加,请定义:

Base.show(io::IO, f::Field{String}) = show(io, f.field_type)
Base.:+(f1::Field{Int8}, f2::Field{Int8}) = f1.field_type + f2.field_type

您可以通过定义来使其更加通用

Base.show(io::IO, f::Field{<:AbstractString}) = show(io, f.field_type)
Base.:+(f1::Field{<:Number}, f2::Field{<:Number}) = f1.field_type + f2.field_type

我定义了 show 而不是 print,因为这样更方便,但您可以为任何您喜欢的 Field{T} 定义任何方法。只需记住不同的 T 会给出不同的类型,这很简单。

我建议您创建另一个便利构造函数:

Field(x::T, d) where {T} = Field{T}(x, d)

现在您不需要在构造函数调用中指定 T

1.7.2> f1 = Field("Hello", "World"); typeof(f1)
Field{String}

1.7.2> f2 = Field(Int8(1), "World"); typeof(f2)
Field{Int8}

1.7.2> print(f1)
"Hello"
1.7.2> f2 + f2
2

You are over-complicating things. You just need to realize that Field{String} and Field{Int8} are two separate types, and treat them as such.

For example:

foo(f::Field{String}) = do_something()
foo(f::Field{Int8}) = do_something_else()

So for printing and adding, define:

Base.show(io::IO, f::Field{String}) = show(io, f.field_type)
Base.:+(f1::Field{Int8}, f2::Field{Int8}) = f1.field_type + f2.field_type

You could make it more generic by defining

Base.show(io::IO, f::Field{<:AbstractString}) = show(io, f.field_type)
Base.:+(f1::Field{<:Number}, f2::Field{<:Number}) = f1.field_type + f2.field_type

instead.

I defined show instead of print, since that is more convenient, but you can define any methods for any Field{T} that you like. Just remember that different T gives different types, and it's easy.

I would recomment that you create another convenience constructor:

Field(x::T, d) where {T} = Field{T}(x, d)

Now you don't need to specify T in the constructor call:

1.7.2> f1 = Field("Hello", "World"); typeof(f1)
Field{String}

1.7.2> f2 = Field(Int8(1), "World"); typeof(f2)
Field{Int8}

1.7.2> print(f1)
"Hello"
1.7.2> f2 + f2
2
方圜几里 2025-01-21 17:43:18

我会考虑使用Base.@kwdefParameters包中更好的等效项。

Base.@kwdef struct Field{T}                          
    field::T                                             
    description::Union{String,Nothing} = nothing          
end                                                  

现在:

julia> Field(field=1)
Field{Int64}(1, nothing)

或:

using Parameters
@with_kw struct Field2{T}
    field::T
    description::Union{String,Nothing} = nothing
end

现在:

julia> Field2(field=1)
Field2{Int64}
  field: Int64 1
  description: Nothing nothing

但是,如果您不想提供名称,您可以这样做:

julia> struct Field3{T}
    field::T
    description::Union{String, Nothing}
    Field3(field::T, description=nothing) where T = new{T}(field, description)
end

现在您可以这样做:

julia> Field3(11)
Field3{Int64}(11, nothing)

I would consider usingBase.@kwdef or a better equivalent in the Parameters package.

Base.@kwdef struct Field{T}                          
    field::T                                             
    description::Union{String,Nothing} = nothing          
end                                                  

And now:

julia> Field(field=1)
Field{Int64}(1, nothing)

or:

using Parameters
@with_kw struct Field2{T}
    field::T
    description::Union{String,Nothing} = nothing
end

And now:

julia> Field2(field=1)
Field2{Int64}
  field: Int64 1
  description: Nothing nothing

However if you do not want to provide the name you can do:

julia> struct Field3{T}
    field::T
    description::Union{String, Nothing}
    Field3(field::T, description=nothing) where T = new{T}(field, description)
end

And now you can just do:

julia> Field3(11)
Field3{Int64}(11, nothing)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文