Язык Julia выпустит версию 1.0 6 августа этого года, и я уверен, что многие люди, наблюдавшие за ним, уже загорелись желанием его попробовать. В этой серии статей будет рассказано о языке Julia на основе некоторых проблем и опыта, которые я действительно испытал во время разработки Yao. Поскольку у меня нет опыта работы с PL, я не буду вдаваться в детали дизайна языка, все начинается с фактического опыта использования.
ОО на Юлии полностью отличается от других языков. Джулия является объектно-ориентированным программным обеспечением, основанным на множественной диспетчеризации и системе типов. Дизайн этой системы также очень умный, поэтому некоторые люди отметили, что производительность Julia во многом обусловлена дизайном языка.
полиморфизм
В Джулии нет классов, но в Джулии вы можете думать обо всем как об объектах, и эти объекты являются экземплярами определенного типа. Таким образом можно объявить составной тип Julia, почти идентичный C. На самом деле в Джулии типы делятся на составные типы (Composite Type), примитивные типы (Primitive Type) и т. д. В этой статье не будет вводиться основной синтаксис, обратитесь к официальной документации (англ.).
struct Kitty
name::String
end
Тогда Джулия не может реализовать полиморфизм, позволив методу принадлежать классу, подобно языкам, таким как Python/C++. Потому что этот тип не может содержать другие методы, кроме собственного конструктора. Джулия использует множественную диспетчеризацию для решения этой проблемы. Что такое множественное распространение? Смотрите мою другую статью:Анализ исходного кода PyTorch (5)
Итак, в Джулии методТипы и взаимодействие между типами, вместоРоль класса в других классах. Преимущества и недостатки традиционного ООП много обсуждались на Zhihu. В области научных вычислений, таких как математика и физика, нам часто нужно определить множество сложных взаимосвязей. Концептуально этот метод более прямой. ООП используется во многих научных исследованиях. вычислительные поля не подходят для этой сцены. ООП Джулии, основанный на нескольких диспетчерах и типах, может быть более подходящей попыткой. Например, сложение числа с плавающей запятой и целого числа
+(lhs::Int32, res::Float64) = # ...
Это дополнение не относится ни к типу Int, ни к типу Float, что имеет математический смысл. Вообще абстрагироваться с Юлией как с теоретическим объектом вполне естественно.
Затем, если вы используете Jupyter Notebook, вы также обнаружите, что связь между методом и типом меньше, потому что метод больше не принадлежит классу. Вы можете сначала определить некоторые методы, затем запустить их в ячейке, а затем определить некоторые методы вместо объявления всех методов в классе.
система типов
Просто наличие множественной отправки обеспечивает лишь некоторый полиморфизм, но не наследование. Это делается системой типов, но помните,Не переносите идеи, унаследованные от традиционного ООП, это ошибка, которая случается со многими новичками на Юлии, особенно с теми, кто перешел с Python/C++. Такой код не является юлианским, потому что в самом языке нет концепции наследования, и вы обнаружите, что в конечном итоге вам придется вручную копировать код, что приведет к большому количеству повторяющегося кода. Конечно, если вы хотите писать ООП-подобный код на Джулии, вы можете это сделать, но я не рекомендую этого делать.
Сначала краткий обзор системы типов. Система типов Джулии представляет собой дерево типов, состоящее из абстрактных и конкретных типов. Подтипы получают поведение супертипа, но не членов супертипа. Итак, Джулия относится к типу «утка». В документации Julia Team подчеркивает:Мы больше заботимся о поведении типа, чем о его членах, поэтому невозможность наследования членов задумана таким образом.
Многие люди спрашивали меня, что, если у меня есть публичные члены, которые должны быть у всех подтипов? Как уменьшить дублирование кода? Ниже я расскажу о нескольких вариантах, пожалуйста, выберите в зависимости от вашей ситуации.
- публичные члены - это некоторые статические члены (не черты типа)
Определяйте общее поведение, а не общих участников
abstract type A end
struct B <: A end
struct C <: A end
name(::A) = "no name" # 默认没有名字
name(::B) = "name B" # B 是另外的名字,而C就继承了A的行为
2. Участники абсолютно одинаковые, но ведут себя по-разному
Используйте Symbol в качестве метки для распределения различных вариантов поведения, но они имеют один и тот же тип параметра.
struct A{Tag}
name::String
end
name(x::A{:boy}) = "the boy's name is $(x.name)"
name(x::A{:girl}) = "the girl's name is $(x.name)"
3. Члены разные, часть публичная и не статическая
В этом случае мы по-прежнему определяем структуру класса через поведение. Нам нужен публичный метод в качестве интерфейса, чтобы нам не приходилось беспокоиться о конкретной структуре класса. Хотя неизбежно вам нужно инкапсулировать публичные члены с новым типом, или вам нужно написать все заново.
struct A
m1
m2
name
end
name(x::A) = x.name
struct B
m1
name
end
name(x::B) = x.name
Таким образом, при использовании типов мы не рекомендуем вызывать члены типа через . , мы рекомендуем вызывать метод, что является поведением при использовании типов. Однако в реальной реализации путем разумного разделения вы обнаружите, что третья ситуация на самом деле возникает относительно редко, а одна или две ситуации возникают чаще. Если вы столкнулись с третьей ситуацией, вы можете подумать еще раз.
Вышеизложенный опыт, резюмируя, таков: поведение (поведение) важнее всего прочего у Юлии.Тип — это просто метка, используемая для отправки действия.