Трейты и линеаризация
От: x-code  
Дата: 14.08.17 11:31
Оценка:
Читаю несколько книжек по Scala и там введены новые сущности — трейты (traits) и "новый тип наследования" — линеаризация.
Но что-то не очень понимаю все это.
А кто нибудь может объяснить на пальцах, в частности как оно устроено на низком уровне, ну и вообще.
С обычным наследованием все вполне понятно, и в общем можно сказать что это достаточно низкоуровневый механизм (если там нет виртуальности) — базовый класс просто включается в производный как его часть. А как устроены трейты?
Re: Трейты и линеаризация
От: dsorokin Россия  
Дата: 14.08.17 16:56
Оценка:
Ну, не такие они уж и новые. Под несколько другим видом все это вместе с линеаризаицией было реализовано в сommon lisp еще в 80-е годы прошлого столетия.

А как это устроено — самому было интересно узнать. Кажется, в scala недавно были большие изменения в этом. По крайней мере, очень надеюсь, что когда-нибудь под андроид можно будет писать на scala без плясок с retroguard. Может быть, уже можно стало с выходом 2.12
Re: Трейты и линеаризация
От: anonymous Россия http://denis.ibaev.name/
Дата: 14.08.17 19:37
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Читаю несколько книжек по Scala и там введены новые сущности — трейты (traits) и "новый тип наследования" — линеаризация. Но что-то не очень понимаю все это.


Это же миксины под другим именем.
Re: Трейты и линеаризация
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.08.17 01:47
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Читаю несколько книжек по Scala и там введены новые сущности — трейты (traits) и "новый тип наследования" — линеаризация.

XC>Но что-то не очень понимаю все это.
XC>А кто нибудь может объяснить на пальцах, в частности как оно устроено на низком уровне, ну и вообще.
XC>С обычным наследованием все вполне понятно, и в общем можно сказать что это достаточно низкоуровневый механизм (если там нет виртуальности) — базовый класс просто включается в производный как его часть.

Считай, что это интерфейсы (в смысле Явы или Шарпа) имеющие реализации методов.

Ну, а линеаризация — это механизм устранения неоднозначностей. В общем случае несколько наследников могут иметь реализации для некоторого метода. Какая из них будет использована определяется порядком в списке наследования.

XC>А как устроены трейты?


Устроены они никак. Это магия времени компиляции. При компиляции из нескольких трэйтов и одного базового класса собирается один класс. Как-то хранится код не знаю.

Мы в Nitra
Автор: VladD2
Дата: 12.01.17
реализовали множественное наследование для абстрактных типов AST и символов. Это очень похоже на трейтсы, но отличается тем, что неоднозначности (конфликты) мы предлагаем разрешать путем переопределения свойства (у нас язык допускает только их) в классе расследующем две или более реализации.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Трейты и линеаризация
От: x-code  
Дата: 15.08.17 05:46
Оценка:
Здравствуйте, anonymous, Вы писали:

A>Это же миксины под другим именем.


В википедии какая-то мутная разница между трейтами и миксинами и вообще непонятно есть ли разница с множественным наследованием. Воспринимается как чистая условность (ну в трейтах только методы, в миксинах еще и поля, в интерфейсах только абстрактные методы, при множественном наследовании можно все). Это действительно так или я упускаю что-то важное?
Re[3]: Трейты и линеаризация
От: anonymous Россия http://denis.ibaev.name/
Дата: 15.08.17 06:09
Оценка:
Здравствуйте, x-code, Вы писали:

XC>В википедии какая-то мутная разница между трейтами и миксинами и вообще непонятно есть ли разница с множественным наследованием. Воспринимается как чистая условность (ну в трейтах только методы, в миксинах еще и поля, в интерфейсах только абстрактные методы, при множественном наследовании можно все). Это действительно так или я упускаю что-то важное?


Так разницы по сути и нет между трейтами и миксинами (ещё есть роли). Точнее каждый язык может сам добавить какое-то контекстное отличие, а может, и функциональное отличие. Например в некоторых объектных системах Perl есть трейты и роли, которые являются одним и тем же, одинаково реализованы, но то или иное название используется в зависимости от контекста.

Разница с множественным наследованием заключается в том, что трейты «не видны» как предки класса, если язык позволяет провести такую интроспекцию.
Re: Трейты и линеаризация
От: vsb Казахстан  
Дата: 15.08.17 06:20
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Читаю несколько книжек по Scala и там введены новые сущности — трейты (traits) и "новый тип наследования" — линеаризация.

XC>Но что-то не очень понимаю все это.
XC>А кто нибудь может объяснить на пальцах, в частности как оно устроено на низком уровне, ну и вообще.
XC>С обычным наследованием все вполне понятно, и в общем можно сказать что это достаточно низкоуровневый механизм (если там нет виртуальности) — базовый класс просто включается в производный как его часть. А как устроены трейты?

В JVM есть понятие "интерфейс", это набор заголовоков методов (ну или класс с абстрактными методами, если говорить по-сиплюсплюсьи). Класс в JVM может наследоваться от одного класса и множества интерфейсов. На этом и построены все трейты. Основная фишка в том, что если в трейте есть свойство, то реально там объявляется абстранктный геттер-сеттер, а потом при наследовании этого трейта в класс вставляется поле и реализуются эти геттеры-сеттеры доступом к этому полю. Вот и всё, в принципе. Ничего сложного на самом деле.
Re[2]: Трейты и линеаризация
От: x-code  
Дата: 15.08.17 08:09
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>В JVM есть понятие "интерфейс", это набор заголовоков методов (ну или класс с абстрактными методами, если говорить по-сиплюсплюсьи). Класс в JVM может наследоваться от одного класса и множества интерфейсов. На этом и построены все трейты. Основная фишка в том, что если в трейте есть свойство, то реально там объявляется абстранктный геттер-сеттер, а потом при наследовании этого трейта в класс вставляется поле и реализуются эти геттеры-сеттеры доступом к этому полю. Вот и всё, в принципе. Ничего сложного на самом деле.


А как там решается проблема ромбовидного наследования? Ведь как я понял, отличие трейтов в Scala от интерфейсов в том что в них могут быть не только абстрактные, но и конкретные поля.
Re[3]: Трейты и линеаризация
От: vsb Казахстан  
Дата: 15.08.17 08:59
Оценка:
Здравствуйте, x-code, Вы писали:

XC>А как там решается проблема ромбовидного наследования? Ведь как я понял, отличие трейтов в Scala от интерфейсов в том что в них могут быть не только абстрактные, но и конкретные поля.


Конкретных полей в трейтах быть не может, JVM такое не поддеживает. Конкретное поле появляется в классе, который реализует трейт. В чём именно проблема ромбовидного наследования? Наверное лучше просто вбить пример и посмотреть что происходит.
Re[3]: Трейты и линеаризация
От: novitk США  
Дата: 18.08.17 14:58
Оценка:
Здравствуйте, x-code, Вы писали:

XC>А как там решается проблема ромбовидного наследования? Ведь как я понял, отличие трейтов в Scala от интерфейсов в том что в них могут быть не только абстрактные, но и конкретные поля.


Проблема ромбовидного наследования есть там где доступ к полям допускается напрямую(C++), а не только через геттеры/сеттеры, как в Скале. Код генерируемый в них компилятором для нижнего узла ромба, как раз зависит от механизма линеаризация.

trait Foo           { var vr: String = ""; val v: String; def foo(): String }
trait A extends Foo { vr = "vrA"; override val v = "vA"; override def foo() = "fooA" }
trait B extends Foo { vr = "vrB"; override val v = "vB"; override def foo() = "fooB" }
println(List(new B with A{}, new A with B {}).map(x => (x.v,x.vr,x.foo)))
---
List((vA,vrA,fooA), (vB,vrB,fooB))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.