linkz
September 29, 2023, 7:11pm
1
I am wondering if when I have two structs, say
mutable struct A{a, b}
str_a::a
str_b::b
end
mutable struct B{a, b, c}
str_a::a
str_b::b
str_c::c
end
and I alias
const A_num = A{<:Number}
const B_num = B{<:Number}
is it possible to create an abstract type, such that A_num
and B_num
would be its subtypes without A
and B
being subtypes of some abstract type?
linkz
September 29, 2023, 7:29pm
3
Well that’s a shame. Would A
and B
have to be subtypes of the same abstract type for it to be possible?
mkitti
September 29, 2023, 7:33pm
5
Could you explain the bigger picture? What are you trying to acccomplish?
linkz
September 29, 2023, 7:36pm
6
Basically trying to avoid code duplication due to A
and B
being different types. I was hoping I could somehow hack an abstract type, say C
, of which A
and B
would be a subtype and have f(x::C)
, rather than f(x::A)
and f(x::B)
(but for a lot of functions).
why do you need to add a type parameter at all?
mkitti
September 29, 2023, 7:38pm
8
Create a box type as follows. Does that help?
julia> abstract type AbstractBox end
julia> struct Box{T} <: AbstractBox
x::T
Box{T}(args...) where T= new{T}(T(args...))
end
julia> Base.getproperty(b::Box, s::Symbol) = getproperty(getfield(b,:x), s)
julia> mutable struct A{a, b}
str_a::a
str_b::b
end
julia> mutable struct B{a, b, c}
str_a::a
str_b::b
str_c::c
end
julia> const A_boxed = Box{A}
A_boxed (alias for Box{A})
julia> const B_boxed = Box{B}
B_boxed (alias for Box{B})
julia> x = A_boxed(1,2)
A_boxed(A{Int64, Int64}(1, 2))
julia> y = B_boxed(3,4,5)
B_boxed(B{Int64, Int64, Int64}(3, 4, 5))
julia> x isa AbstractBox
true
julia> y isa AbstractBox
true
julia> x.str_a
1
julia> x.str_b
2
julia> y.str_a
3
julia> y.str_b
4
julia> y.str_c
5
Edit : For completeness and tab completion:
Base.propertynames(x::Box) = Base.propertynames(getfield(x, :x))
1 Like
linkz
September 29, 2023, 7:40pm
9
It’s a complex codebase with lots of functions that depending on the input type would have to do different things in certain parts.
linkz
October 2, 2023, 9:30am
10
This is very close to what I need, except that I can’t really do (otherwise it breaks with the rest of the code that is)
x = A_boxed(1, 2)
y = B_boxed(3, 4, 5)
but I have to keep
x = A_boxed(1, 2)
y = B_boxed(3, 4, 5)
Thank you for your attempts, but I think I’ll pursue a different approach.
You can always do
julia> mutable struct A{a, b}
str_a::a
str_b::b
end
julia> mutable struct B{a, b, c}
str_a::a
str_b::b
str_c::c
end
julia> const A_num = A{<:Number, <:Number}
A_num (alias for A{<:Number, <:Number})
julia> const B_num = B{<:Number, <:Number, <:Number}
B_num (alias for B{<:Number, <:Number, <:Number})
julia> const AB_num = Union{A_num, B_num}
AB_num (alias for Union{A{<:Number, <:Number}, B{<:Number, <:Number, <:Number}})
julia> A("", 2) isa AB_num
false
julia> B(1//2, 2, 3/0) isa AB_num
true
julia> B(1//2, 2, 3/0)
B_num{Rational{Int64}, Int64, Float64}(1//2, 2, Inf)
What you cannot do is have one package create an abstract type encompassing both A_num
and B_num
(AB_num
in the example) and then have another package define a new subtype struct C_num <: AB_num
. For that kind of stuff, you should look at Holy traits.
1 Like