Is there a way to hide a default constructor for a struct so that it is not callable?
Thanks.
Is there a way to hide a default constructor for a struct so that it is not callable?
Thanks.
You can certainly replace the default constructor by a custom one. But dropping it without any replacement isn’t particularly useful, is it? If there is no constructor at all, what do you need the struct for (you will never be able to create objects)?
julia> struct A
x::Float64
A() = new(1.23)
end
julia> A() # custom constructor
A(1.23)
julia> A(3.141) # default constructor isn't defined
ERROR: MethodError: no method matching A(::Float64)
Closest candidates are:
A() at REPL[1]:3
Stacktrace:
[1] top-level scope
@ REPL[3]:1
FWIW, you can also delete the constructor methods after defining the struct.
julia> struct A
x::Float64
end
julia> Base.delete_method.(methods(A));
julia> methods(A)
# 0 methods for type constructor
julia> A()
ERROR: MethodError: no method matching A()
But again, I don’t get the point and wouldn’t recommend it
You can also disable the default constructor by making struct
dependent on another (arbitrary) type:
struct A{T}
x::Float64
end
A(3.1) # error
A{Any}(3.1) # works
You can also just do this:
julia> struct A
f() = nothing
end
julia> methods(A)
# 0 methods for type constructor
Is this behavior to be considered a bug or a feature?
No idea. It certainly looks buggy and arguably it should error out - but it doesn’t.
That was also my impression…
julia> struct A{F}
f() = println("Hello world")
x::F
A() = new{typeof(f)}(f)
end
julia> A().x()
Hello world
julia> A()
A{var"#f#4"}(var"#f#4"())
julia> f()
ERROR: UndefVarError: `f` not defined
Stacktrace:
[1] top-level scope
@ REPL[10]:1
Still not sure :D: Wrongly named inner constructor doesn't error · Issue #52580 · JuliaLang/julia · GitHub
Not a bug. The struct has local scope and you can evaluate arbitrary code inside to define ways to construct objects of the type. The most common way to do this is to add methods to the type object itself, but you can do other things as well, eg define a single globally bound instance or a global function by another name that constructs them. If there is any code in a strict you don’t get a default constructor.
No variable assignments in the struct’s outermost scope, right, it throws a syntax error?
These could’ve been done in the global scope without global declarations or eval
s. Is there anything that must be done in the struct
’s local scope besides the inner constructors?
Yes, there are some syntax restrictions—it can’t clash with field declaration or the reserved syntax for defining default values for them.
The point of doing these things inside the struct is that it’s easy to prove that they are the only ways that an object of the type can be constructed since the new pseudo-function is only available inside there. If you do it outside then you had to make some constructor method available and anyone could call that so there’s no such guarantee.
Just note this is not 100% true… in ConstructionBase.jl we actually do construct objects without constructors! (like anonymous function functors)