As may be apparent by my use of the word “child”, I come from an OOP background. I want to replicate some code I have in Python in Julia as I find this language amazing.
I created a simplified example for below, but I want to create a struct array type that contains a multidimensional array of integers along with some fields for metadata. I originally went about writing out every function overload that was required (some 500 lines) before coming to a dead end where dispatch wasn’t selecting the functions I had created.
I then found reference to AbstractArray subtyping and went down that path. While there are two very informative examples there, I’m still struggling.
Here is my example where I accept any set of data (numbers) and if signed store it straight away and if unsigned, absolute it (a silly example but it represents what I need solved):
struct SignedArray{T,N} <: AbstractArray{T,N}
data :: Array{T,N}
sign :: String
function SignedArray(data :: Array{T, N}, sign :: String) where {T, N}
if sign == "signed"
return new{typeof(data), ndims(data)}(data, sign)
elseif sign == "unsigned"
return new{typeof(data), ndims(data)}(abs.(data), sign)
end
end
end
Base.size(S :: SignedArray) = size(S.data)
Base.getindex(S :: SignedArray{T, N}, I::Vararg{Int, N}) where {T, N} = get(S.data, I, zero(Int))
Base.similar(S :: SignedArray, ::Type{T}, dims::Dims) where {T} = SignedArray{T}([],"signed")
Base.setindex!(S :: SignedArray{T, N}, v, I::Vararg{Int, N}) where {T, N} = (S.data[I] = v)
Base.length(S :: SignedArray{T, N}) where {T, N} = prod(size(S.data))
I’m pretty certain that I am declaring the similar
function wrong as I don’t quite understand its function. Furthermore, if I now go about trying to instantiate a struct i.e.
R = SignedArray([1,2,3,4], "unsigned")
I get the following error:
MethodError: Cannot `convert` an object of type Int64 to an object of type Vector{Int64}
If I look at the dictionary example for sub-typing an AbstractArray in the documentation (see link above), it would seem that none of the constructors actually store the data in the data
field i.e:
SparseArray(::Type{T}, dims::NTuple{N,Int}) where {T,N} = SparseArray{T,N}(Dict{NTuple{N,Int}, T}(), dims);
which makes little sense to me, but perhaps that is the flaw in my understanding?
Any help with this problem or my lack of understanding of it would be very very helpful.
Thank you all.