首页 > 解决方案 > Julialang:在抽象类型上强制执行接口

问题描述

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

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

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

所以我有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

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

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

>"elroy"

因此,即使MusicStudent是 的子类型AbstractPersonMusicStudent也没有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

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

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

标签: julia

解决方案


基本答案是,在 julia 中,方法的接口被认为是定义为采用该类型元素的方法。AbstractArray例如指定实现应该实现getIndexand size。不将字段作为接口的一部分的原因是不这样​​做允许内存高效的代码,因为每种类型都可以以最明智的方式定义方法。例如,如果我想Bob为所有名为 bob 的人创建一个名为的类型,我不想每次都存储他的名字。通过使用方法,Julia 以意想不到的方式为未来的扩展提供了更多的潜力。

从技术上讲,这种方法会失去“安全性”,但唯一的方法是使用可能不存在的字段编写代码,在这种情况下会出错。这种类型的安全性并不是很有用,因为它只会给您一个编译错误,从而减慢开发速度。


推荐阅读