Julialang: применение интерфейсов на абстрактных типах - PullRequest
3 голосов
/ 11 июня 2019

Я пытался понять систему типов для Julialang, но некоторые аспекты дизайна все еще смущают меня. Я надеялся, что кто-то сможет уточнить.

Итак, вопрос здесь об абстрактных типах и их конкретных реализациях. Из того, что я понимаю Julia Абстрактные типы не накладывают каких-либо ограничений на их конкретные реализации. Таким образом, нет гарантии, что метод, который работает с типом Abstract, будет работать с конкретной реализацией этого типа.

Я понял, что Джулия не использует классы и не наследует. Но я просто хочу избежать появления всевозможных ошибок в моем коде. Если есть другая парадигма дизайна, то кто-то может ответить на вопрос 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 является подтипом 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

Итак, проблема в том, что Julia позволяет мне создать экземпляр переменной типа m1 с по существу неполным конструктором. И это только дает мне ошибку, когда я пытаюсь запустить эту функцию.

То есть, если я напишу функцию для абстрактного типа, я не могу гарантировать, что каждая конкретная реализация этого типа имеет один и тот же интерфейс. Кажется, что это сделает очень хрупкий код, так как разработчик не будет знать, какие типы реализуют какие атрибуты и методы.

Ответы [ 2 ]

2 голосов
/ 11 июня 2019

Разве такое поведение не является просто ошибкой в ​​реализации Persons?Если вы действительно хотите, чтобы поведение прошло без исключения, вы можете определить метод по умолчанию:

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)
""

Я думаю, что основная борьба может заключаться в том, что в Джулии вы не можете унаследовать поле данных с именем "name" как частьиерархия объектов.Здесь есть хорошее обсуждение этой подлинной проблемы (см. Упоминание макроса @forward):

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

1 голос
/ 11 июня 2019

Основной ответ заключается в том, что в julia интерфейс метода рассматривается как методы, которые определены для получения элемента этого типа. Например, AbstractArray указывает, что реализации должны реализовывать getIndex и size. Причина, по которой поля не становятся частью интерфейса, заключается в том, что их отсутствие позволяет использовать эффективный для памяти код, поскольку каждый тип может определять методы наиболее разумным образом. Например, если я хочу создать тип с именем Bob, который является подтипом для всех людей с именем bob, я не хочу хранить его имя каждый раз. используя методы, Джулия предоставляет гораздо больший потенциал для будущего расширения неожиданными способами.

Технически этот подход теряет «безопасность», но единственный способ это сделать, если вы пишете код, используя поля, которые могут не существовать, в этом случае вы получите ошибку. Этот тип безопасности не так полезен, поскольку он просто дает вам ошибку компиляции, которая замедляет разработку.

...