Julialang:在抽象类型上强制执行接口

kri*_*nab 7 julia

我一直在尝试理解类型系统,Julialang但某些设计方面仍然让我感到困惑。我希望有人能够澄清。

所以这里的问题是关于抽象类型及其具体实现。据我了解 Julia,抽象类型不会对其具体实现施加任何限制。因此,不能保证适用于抽象类型的方法也适用于该类型的具体实现。

我知道 Julia 不使用类或遵循继承。但我只是想避免在我的代码中产生各种错误。如果有不同的设计范式,那么有人可以回答下面的问题2。

所以我有两个问题。

  1. 这仍然是语言的工作方式吗?只是为了确认自博客发布以来没有任何变化。

  2. 用户如何围绕这个看似存在的漏洞设计他们的软件?

链接帖子中的问题示例:

abstract type AbstractPerson end
abstract type AbstractStudent <: AbstractPerson end
abstract type AbstractTeacher <: AbstractPerson end

struct Person <: AbstractPerson
  name::String    
end

struct Student <: AbstractStudent
  name::String  
  grade::Int
  hobby::String
end

struct MusicStudent <: AbstractStudent
  grade::Int
end
Run Code Online (Sandbox Code Playgroud)

现在,如果我在抽象类型上创建一些方法。

get_name(x::AbstractPerson) = x.name
p1 = Person("elroy")
get_name(p1)

>"elroy"
Run Code Online (Sandbox Code Playgroud)

因此,即使MusicStudent是 的子类型AbstractPerson,它MusicStudent也没有name属性。这意味着观察到以下行为。

m1 = MusicStudent(10)
get_name(m1)


ERROR: type MusicStudent has no field name

Stacktrace:
 [1] getproperty(::Any, ::Symbol) at ./sysimg.jl:18
 [2] get_name(::MusicStudent) at ./In[2]:1
 [3] top-level scope at In[13]:2
Run Code Online (Sandbox Code Playgroud)

所以这里的问题是Julia允许我使用本质上不完整的构造函数来实例化类型变量m1。当我尝试运行该函数时,它只会给我一个错误。

因此,这意味着如果我为抽象类型编写一个函数,我无法保证该类型的每个具体实现都具有相同的接口。这似乎会产生非常脆弱的代码,因为开发人员不知道哪些类型实现哪些属性和方法。

Bil*_*ill 4

这种行为难道不是 Person 实现中的一个错误吗?如果你真的希望行为没有异常,你可以定义一个默认方法:

julia> get_name(p::AbstractPerson) = try return p.name catch y return "" end
get_name (generic function with 1 method)

julia> m1 = MusicStudent(10)
MusicStudent(10)

julia> get_name(m1)
""
Run Code Online (Sandbox Code Playgroud)

我认为潜在的困难可能是在 Julia 中你无法继承名为“name”的数据字段作为对象层次结构的一部分。这里对这个真正的问题进行了很好的讨论(请参阅@forward宏的提及):

https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231