gpt4 book ai didi

types - 什么是 Julian 替代属性继承?

转载 作者:行者123 更新时间:2023-12-01 11:21:14 25 4
gpt4 key购买 nike

在许多编程语言中,父类可以要求任何子类包含特定字段。

如果字段是静态的,在 Julia 中可以通过以下方式实现相同的效果。

julia> abstract Fruit

julia> type Apple <: Fruit end

julia> type Orange <: Fruit end

julia> type Banana <: Fruit end

julia> color(::Apple) = :red
color (generic function with 1 method)

julia> color(::Orange) = :orange
color (generic function with 2 methods)

julia> color(::Banana) = :yellow
color (generic function with 3 methods)

但是,如果字段是动态的,这将不起作用。在下面的例子中,我想要求 Pet 的任何子类型包含字段 name .
julia> abstract Pet

julia> type Cat <: Pet
name::String
hairless::Bool
end

julia> type Dog <: Pet
name::String
end

julia> abstract Bird <: Pet

julia> type Parrot <: Bird
name::String
color::Symbol
end

julia> type Conure <: Bird
name::String
end

julia> feet(::Cat) = 4
feet (generic function with 1 method)

julia> feet(::Dog) = 4
feet (generic function with 2 methods)

julia> feet(::Bird) = 2
feet (generic function with 3 methods)

类型必须不同,因为它们也可能具有其他属性,并且可以为每种类型唯一定义方法。
  • 我如何执行此要求?理想情况下,我不必指定 name任何子类型中的字段,但如果我必须,就这样吧。
  • 如果这在 Julia 中是不可能的,那么建议的替代方案是什么?我可以重构这种类型的代码以完全消除这种行为的需要吗?
  • 最佳答案

    我如何强制执行?

    有测试

    using Base.Test 
    @testset "Field Contract" begin
    for sub in subtypes(Pet)
    @test fieldtype(sub, :name) == String
    #will error if no field names string.
    #will fail if it is has wrong type
    end
    end

    如何在子类型上自动填充它

    在技​​术上可以通过元编程来做到这一点。
    我不推荐它。
    这只是一个 hack 概念证明:
    macro declare_abstract(typename, fields...)
    quote
    abstract $(esc(typename))
    const $(esc(Symbol(:__abfields_,typename))) = $(esc(fields))
    $(esc(typename))
    end
    end

    error("Please don't use this in real code") #prevent trivial copy paste

    macro declare(type_expr)
    @assert type_expr.head == :type
    @assert type_expr.args[2].head == :(<:)
    parent_typename::Symbol = type_expr.args[2].args[2]
    if isdefined(Symbol(:__abfields_, parent_typename))
    @assert type_expr.args[3].head == :block
    abfields = eval(Symbol(:__abfields_, parent_typename)) #Read a globel constant. Iffy practice right here -- using eval in a macro

    push!(type_expr.args[3].args, abfields[1].args...)
    end
    type_expr
    end

    用法示例:
    @declare_abstract Pet (name::String), (owner_id::Int)
    @declare type Cat <: Pet
    end

    核实:
    ?Cat
    ...

    Summary:
    type Cat <: Pet
    Fields:
    name :: String
    owner_id :: Int64

    等待?你为什么说不要这样做?

    这是一种代码气味。
    不应该依赖抽象类型的字段。

    Julia 还不够完善,无法制定这些约定,
    与标准解决方案。
    这里我从我自己的经验谈起。

    如果您的方法采用 Abstract 类型作为参数。
    那么它应该取决于实现类型的方法;
    但不是在实现类型的字段上。
    这也适用于 Informal Interfaces也。

    当您发现需要一个没有此字段的子类型时,它会使您的代码变得不灵活。
    它发生在我身上。
    我想我知道所有的子类型,但后来我意识到我想将其他人的某些东西作为子类型包装起来,而这个字段对此毫无意义。我所有的代码都断了

    我不是在这里讨论组合与继承的争论。虽然那是相关的。

    例子

    例如,
    如果您需要处理不符合您假设的宠物怎么办。
    也许你包装牲畜包裹的东西。
    这些宠物实际上是 Bees它们没有名称字段,因为它们没有名称。
    他们有一个 hive字段,但它是 Int .

    如果你正在使用方法,你会没事的:
    假设你有一个 get_identifier方法

    对于您已经准备好的类型: get_identifier(x::Union{Dog,Cat})=x.name
    接着来介绍一下与 Bee的兼容性类型
    您只需添加 get_identifier(x::Bee)="Member of hive# $(x.hive)" .
    并且您的所有代码都有效。

    另一方面,如果你有 x.name在你的代码中到处都是,那么它就会全部中断。
    当然你可以向构造函数添加一些东西,它会自动设置一个名称字段。 (当我发现自己处于这种情况时,我就是这样做的)。
    但这是一个黑客和维护负担。
    当然,这个例子中的小。

    异常(exception)

    当然,这条规则有一个异常(exception):
    当你真的知道所有子类型的字段时。
    例如,如果我编写了一个解决特定问题系列的数学求解器。我有一个类型为 AbstractResults ,我解决的每种类型的问题都有自己的具体子类型,用于存储此类结果的特殊因素;然后我知道我家只有 5 种可能的问题。
    所以我知道 AbstractResults 只有 5 个具体的子类型。 ,
    我知道他们因此都拥有我给他们的实现;没有其他字段集是有意义的。 (如果都是非常简单的类型,则可行)。
    然后就可以了。
    只是不要错。

    测试

    您也可以检查方法是否使用一些测试代码实现
    using Base.Test 
    @testset "Method Contract" begin
    for sub in subtypes(Pet)
    @test method_exists(get_identifier, (sub,))
    end
    end

    这种“通过测试强制执行契约”是一种动态语言模式。

    结论

    靠方法更正确。
    方法定义功能。
    字段只是一个实现细节。
    作为抽象类型的定义者,更重要的是使用抽象类型的方法的定义者,您非常清楚每个子类型必须具有的功能。
    你不太确定实现。

    如果您的方法将抽象类型的字段作为参数,
    考虑它是否完全以正确的方式编写

    关于types - 什么是 Julian 替代属性继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42641243/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com