I’m studying Julia’s Holy traits along with traits in Rust, Scala and the original traits paper, “Traits: A Mechanism for Fine-grained Reuse”. I want to use a trait Color defined in ColorModule outside of its module. I wrote the following code:
module ColorModule
abstract type Color end
struct Blue <: Color end
printlncolor(x) = printlncolor(Color(x), x)
printlncolor(::Blue, ::Any) = println("blue")
end
using .ColorModule
struct Kingfisher end
ColorModule.Color(::Kingfisher) = ColorModule.Blue() # is this line safe?
kingfisher = Kingfisher()
ColorModule.printlncolor(kingfisher)
Is this safe code, or am I missing something important? I’m worrying the line of the definition of ColorModule.Color(::Kingfisher).
How to use exported names? The following can’t go well.
module ColorModule
export Color, Blue, printlncolor
abstract type Color end
struct Blue <: Color end
printlncolor(x) = printlncolor(Color(x), x)
printlncolor(::Blue, ::Any) = println("blue")
end
using .ColorModule
struct Kingfisher end
Color(::Kingfisher) = Blue()
kingfisher = Kingfisher()
printlncolor(kingfisher) # ERROR: MethodError: no constructors have been defined for Main.ColorModule.Color
You should keep that definition since you are extending it. Alternatively, you could do import ColorModule: Color.
export or public (as of Julia 1.11) can serve as indicators that the name is intended to be used outside of the module. Typically, you should not be reaching into modules to use things that are not declare for public use. This is independent of the use of qualified syntax.