Я относительно знаком с Go, написав в нем несколько небольших программ. Руст, конечно, я менее знаком с, но следить за.
Прочитав недавно http://yager.io/programming/go.html , я подумал, что лично я рассмотрю два способа обработки Generics, потому что статья, похоже, несправедливо критикует Go, когда на практике интерфейсов было немного не мог сделать элегантно. Я продолжал слышать шумиху о том, насколько сильны черты Руста, и не что иное, как критика людей о Го. Имея некоторый опыт в го, я удивлялся, насколько это было правдой и каковы были различия в конечном итоге. Я обнаружил, что черты и интерфейсы очень похожи! В конечном счете, я не уверен, что что-то упустил, так что вот краткое образовательное краткое изложение их сходства, так что вы можете сказать мне, что я пропустил!
Теперь давайте посмотрим на интерфейсы Go из их документации :
Интерфейсы в Go предоставляют способ указать поведение объекта: если что-то может сделать это, то его можно использовать здесь.
Безусловно, самый распространенный интерфейс - Stringer
это строка, представляющая объект.
type Stringer interface {
String() string
}
Таким образом, любой объект, который String()
определен на нем, является Stringer
объектом. Это может быть использовано в сигнатурах типа, которые func (s Stringer) print()
берут почти все объекты и печатают их.
У нас также есть, interface{}
который принимает любой объект. Затем мы должны определить тип во время выполнения через отражение.
Теперь давайте взглянем на Rust Traits из их документации :
В простейшем случае признак - это набор из нуля или более сигнатур метода. Например, мы могли бы объявить черту Printable для вещей, которые можно распечатать на консоли, с единственной сигнатурой метода:
trait Printable {
fn print(&self);
}
Это сразу выглядит очень похоже на наши интерфейсы Go. Единственное отличие, которое я вижу, состоит в том, что мы определяем «реализации» черт, а не просто определяем методы. Итак, мы делаем
impl Printable for int {
fn print(&self) { println!("{}", *self) }
}
вместо
fn print(a: int) { ... }
Дополнительный вопрос: что происходит в Rust, если вы определяете функцию, которая реализует черту, но вы не используете impl
? Это просто не работает?
В отличие от интерфейсов Go, система типов в Rust имеет параметры типа, которые позволяют вам делать правильные обобщения и тому подобное, в interface{}
то время как компилятор и среда выполнения фактически знают тип. Например,
trait Seq<T> {
fn length(&self) -> uint;
}
работает с любым типом, и компилятор знает, что тип элементов Sequence во время компиляции, а не с использованием отражения.
Теперь актуальный вопрос: я здесь скучаю? Являются ли они на самом деле , что подобное? Разве нет более фундаментальной разницы, что я здесь упускаю? (При использовании. Детали реализации интересны, но в конечном итоге не важны, если они функционируют одинаково.)
Помимо синтаксических различий, фактические различия, которые я вижу:
- Go имеет автоматическую отправку метода против Rust требует (?)
impl
Для реализации черты- Элегантный против Явного
- В Rust есть параметры типа, которые позволяют создавать собственные дженерики без отражения.
- Go действительно не имеет ответа здесь. Это единственное, что значительно более мощно, и в конечном итоге это просто замена для копирования и вставки методов с разными типами подписей.
Это единственные нетривиальные различия? Если так, то кажется, что система интерфейса / типа Go на практике не так слаба, как кажется.
AnyMap
- хорошая демонстрация сильных сторон Rust, объединяющая объекты-черты с обобщениями, чтобы обеспечить безопасную и выразительную абстракцию хрупкой вещи, которую в Go необходимо будет написатьmap[string]interface{}
.