Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: BoneFlute 18. 12. 2020, 00:25:06
-
Zdravím. Měl bych tu zase něco z akademického programování.
Předpokládejme nějaký supr jazyk. A chceme tam mít podporu traitů - aby nedocházelo ke zneužívání dědičnosti. Takže například:
trait A {
private int id;
public int getId() { return this.id; }
}
trait B {
private string name;
public string getName() { return this.name; }
}
class Foo {
use A;
use B;
}
Otázka zní, jak hodnoty z těch traitů inicializovat? A navíc můžeme předpokládat, že třída komponující traity by neměla mít právo přistupovat k privátním členům.
Určitě nechceme settery, potřebujeme konstruktor, abychom měli kontrolu nad stavem objektu. Jak tento problém řešit?
Děkuji za příspěvky, ať už z reálných jazyků, nebo klidně pouhá úvaha.
-
Mě napadají dvě řešení:
class Foo {
use A;
use B;
public constructor(int id, string name) {
A.constructor(id);
B.constructor(name);
}
}
nebo odvážnější:
trait A {
readonly int id;
}
trait B {
readonly string name;
}
class Foo {
use A;
use B;
readonly Address address;
// konstruktor se vygeneruje automaticky, na základě příznaku "readonly", a případně se může přetížit.
public constructor(string name, Address address) {
this.constructor(null, name, address);
}
}
-
V Rustu, pokud vím, trait nemá fieldy. Proč je tam potřebuješ mít, patří tam vůbec?
-
V Rustu, pokud vím, trait nemá fieldy. Proč je tam potřebuješ mít, patří tam vůbec?
Ve Scale ano.
-
Jak psali přede mnou, Rustovské traity fieldy nemají, a nemám pocit, že by mi tam chyběly.
Scala je má, inicializují se přímo v definici traitu
trait T {
val f: Integer = 1
}
class C extends T {
def printF(): Unit = {
println(f)
}
}
Kdybych chtěl inicializaci odložit, tak z toho fieldu udělám abstraktní metodu, používá se to stejně jako field.
trait T {
def f: Integer
}
class C(val f: Integer) extends T {
def printF(): Unit = {
println(f)
}
}
-
Podle me fieldy do traitu nepatri.
Pokud chci jen rict "tahle vec umi vratit id" a "tahle vec umi vratit jmeno" tak na to jsou interfacy/protokoly.
A ten priklad s getterama mi dost smrdi zneuzivanim traitu (k dedicnosti?).
Podle me trait ma prinest chovani a ne nejak obalovat hodnoty.
Skoro se desim predstavy ze by to dokonce mohli byt nejaky mutable fieldy.
No ale jestli to musi bejt a jestli to teda muzou bejt konstanty... tak bych uprednostnil neco takoveho:
class Foo {
use A with id;
use B with name;
Address address;
}
'readonly' neni treba, protoze vsechno je readonly.... a z toho 'with id' by si uz kompiler mohl odvodit jak ma vypadat konstruktor.
-
Obecně se domnívám, že data do traitů nepatří, ale kdyby nebylo zbytí, tak by se mi líbilo něco jako setAssociatedObject v Objective-C, to je hezky transparentní, kód zůstane čistý a všichni jsou spokojení. Jen teda asi nemáme žádný jazyk s traity a runtimem, který by to umožňoval. Třeba jednou vznikne nějaký Objective-Rust :)
-
Co se týče námitky, zda do traitů patří data, a tak.
V jednom z mejch DSL mám něco takového:
Person = {
name: String
surname: String
}
ACL = {
roles: [Role]
permissions: [Permission]
extraPermissions: [Permission]
}
UserAcount = {
login: String
password: Password
email: Email
... Person
... ACL
}
Přijde mi to celkem užitečné a zpřehledňující. Co byste tomu vytkly?
Jak byste řešili konstruktory?
-
V Rustu, pokud vím, trait nemá fieldy. Proč je tam potřebuješ mít, patří tam vůbec?
Předpokládejme, že ano.
Motivace traitů, tak jak o ní v tomto vlákně mluvím, je komponovat "objekt" z částí. Tedy něco na co se zneužívá dědičnost, ale bez nevýhod dědičnosti.
-
class C(val f: Integer) extends T {
def printF(): Unit = {
println(f)
}
}
Tohle je docela hezký.
Jde nějak ještě když bych tomu chtěl přidat nějakou logiku? Tedy konstruktor přijme f, přepočítá ho, a teprve výsledek uloží do fieldu f?
-
Motivace traitů, tak jak o ní v tomto vlákně mluvím, je komponovat "objekt" z částí. Tedy něco na co se zneužívá dědičnost, ale bez nevýhod dědičnosti.
Takže něco jako implicitní kompozice v Go?
-
Motivace traitů, tak jak o ní v tomto vlákně mluvím, je komponovat "objekt" z částí. Tedy něco na co se zneužívá dědičnost, ale bez nevýhod dědičnosti.
Takže něco jako implicitní kompozice v Go?
Go moc dobře neznám. Ale vypadá to, že ano.
-
Motivace traitů, tak jak o ní v tomto vlákně mluvím, je komponovat "objekt" z částí. Tedy něco na co se zneužívá dědičnost, ale bez nevýhod dědičnosti.
Takže něco jako implicitní kompozice v Go?
Go moc dobře neznám. Ale vypadá to, že ano.
To by dávalo smysl a je to v podstatě jednoduché na implementaci i používání.
-
V Rustu, pokud vím, trait nemá fieldy. Proč je tam potřebuješ mít, patří tam vůbec?
Předpokládejme, že ano.
Motivace traitů, tak jak o ní v tomto vlákně mluvím, je komponovat "objekt" z částí. Tedy něco na co se zneužívá dědičnost, ale bez nevýhod dědičnosti.
Eee?! Tomu co vidím tady https://forum.root.cz/index.php?topic=24024.msg341967#msg341967 se říká kompozice a traity k tomu nepotřebuju. Traity mi k objektu přimíchají další chování aniž bych si musel uložit do fieldu jejich instance.
Nebo mi něco uniká?
Souhlasím, že construktory by měly být součástí rozhraní. Vlastně bych kostruktory nejradši zrušil a zavedl místo nich kategorii pro faktory metody a těm umožnil být (volitelně) součástí do rozhraní/traitu. Fieldy mi v traitech nevadí. S dynamických dispatch by to byl super jazyk.
Pragmaticky a přitom docela dobře to má udělané Groovy http://docs.groovy-lang.org/next/html/documentation/core-traits.html
-
V Rustu, pokud vím, trait nemá fieldy. Proč je tam potřebuješ mít, patří tam vůbec?
Předpokládejme, že ano.
Motivace traitů, tak jak o ní v tomto vlákně mluvím, je komponovat "objekt" z částí. Tedy něco na co se zneužívá dědičnost, ale bez nevýhod dědičnosti.
Eee?! Tomu co vidím tady https://forum.root.cz/index.php?topic=24024.msg341967#msg341967 se říká kompozice a traity k tomu nepotřebuju. Traity mi k objektu přimíchají další chování aniž bych si musel uložit do fieldu jejich instance.
Ee, kompozice v kontextu OOP je trochu něco jiného. Já chci, aby výsledek bylo toto:
UserAcount = {
login: String
password: Password
email: Email
name: String
surname: String
roles: [Role]
permissions: [Permission]
extraPermissions: [Permission]
}
Jestli tomu budeme říkat traity, nebo jinak je mi celkem jedno.
Zatím jsme tu probrali, zda to je či není dobrý nápad.
Takže ještě k mé otázce - jak tyto vlastnosti inicializovat, případně když ta inicializace má nějakou komplexní logiku. Proč by to měl být problém souvisí poněkud s tím, že ty fieldy z traitu jsou privátní, mají nějaký provázaný stav, který by si měl hlídat ten trait.
Souhlasím, že construktory by měly být součástí rozhraní. Vlastně bych kostruktory nejradši zrušil a zavedl místo nich kategorii pro faktory metody a těm umožnil být (volitelně) součástí do rozhraní/traitu. Fieldy mi v traitech nevadí. S dynamických dispatch by to byl super jazyk.
Pragmaticky a přitom docela dobře to má udělané Groovy http://docs.groovy-lang.org/next/html/documentation/core-traits.html
Na to groovy jsem koukal, a nenašel jsem tam ukázku, jak se ty fieldy inicializují.
Pro demonstraci předpokládáme situaci, kdy do existující třídy přidáme nový trait, takže musím přepsat konstruktory té třídy, to se má samo sebou. Otázka je, jak to bude vypadat.
-
V první otázce zní: Nezneužívat dědičnost, radši na to vzít traity. Já říkám: Ale já vidím kompozici, k té traity nepotřebuju. Odpověď: V kontextu OOP je to jinak. Tak jak je to? Co je trait?
Abych nebyl za kverulanta, já bych prostě inicializoval v konstruktoru, kde bych volal konstruktor traitu. Nebo je myšlena nějaká automatická inicializace? Asi nerozumím té otázce. Je to otázka po syntaxi, sémantice, runtime? Všechno je možný - můžu inicializovat aspektem, anotací...
-
V první otázce zní: Nezneužívat dědičnost, radši na to vzít traity. Já říkám: Ale já vidím kompozici, k té traity nepotřebuju. Odpověď: V kontextu OOP je to jinak. Tak jak je to? Co je trait?
To máš buřt.
Abych nebyl za kverulanta, já bych prostě inicializoval v konstruktoru, kde bych volal konstruktor traitu. Nebo je myšlena nějaká automatická inicializace? Asi nerozumím té otázce. Je to otázka po syntaxi, sémantice, runtime? Všechno je možný - můžu inicializovat aspektem, anotací...
Takhle?:
class Foo {
use A;
use B;
public constructor(int id, string name) {
A.constructor(id);
B.constructor(name);
}
}
Asi nerozumím té otázce. Je to otázka po syntaxi, sémantice, runtime? Všechno je možný - můžu inicializovat aspektem, anotací...
Syntaxe.
Jak tyto vlastnosti inicializovat, případně když ta inicializace má nějakou komplexní logiku. Proč by to měl být problém souvisí poněkud s tím, že ty fieldy z traitu jsou privátní, mají nějaký provázaný stav, který by si měl hlídat ten trait.
-
class C(val f: Integer) extends T {
def printF(): Unit = {
println(f)
}
}
Tohle je docela hezký.
Jde nějak ještě když bych tomu chtěl přidat nějakou logiku? Tedy konstruktor přijme f, přepočítá ho, a teprve výsledek uloží do fieldu f?
Místo konstruktoru použiješ faktory metodu, typicky v associated objectu třídy.
trait T {
def f: Integer
}
class C(val f: Integer) extends T {
def printF(): Unit = {
println(f)
}
}
object C {
def apply(s: String): C = {
new C(s.toInt)
}
}
object Main {
def main(args: Array[String]): Unit = {
C("11").printF()
}
}
Ale taky mám radši composition over inheritance. Kdybych chtěl skládat tvůj UserAccount podle toho vzoru co ukazuješ, použil bych kompozici. I když by to ve Scale šlo poskládat z traitů s fieldy jak chceš, nelíbilo by se mi, že v definici UserAccount není jasně na jednom místě vidět, jaké fieldy nakonec v té třídě budou, člověk si musí projít všechny traity zvlášť, a přitom fieldy a jejich typy bývají pro porozumění kódu většinou to nejdůležitější.
-
... nelíbilo by se mi, že v definici UserAccount není jasně na jednom místě vidět, jaké fieldy nakonec v té třídě budou, člověk si musí projít všechny traity zvlášť, a přitom fieldy a jejich typy bývají pro porozumění kódu většinou to nejdůležitější.
On ten dotaz tak trochu vycházel z mého požadavku toho DSLka. Kde se to používá trochu naopak. Většinou si prohlížíš ten výsledný typ, se všema fieldama a behaviours, co to cestou posbíralo. A teprve sekundárně doklikáváš, kde je to nadefinované.
Ale pokud tě napadá jaká další úskalí to může mít, sem s tím.
-
V první otázce zní: Nezneužívat dědičnost, radši na to vzít traity. Já říkám: Ale já vidím kompozici, k té traity nepotřebuju. Odpověď: V kontextu OOP je to jinak. Tak jak je to? Co je trait?
To máš buřt.
Abych nebyl za kverulanta, já bych prostě inicializoval v konstruktoru, kde bych volal konstruktor traitu. Nebo je myšlena nějaká automatická inicializace? Asi nerozumím té otázce. Je to otázka po syntaxi, sémantice, runtime? Všechno je možný - můžu inicializovat aspektem, anotací...
Takhle?:
class Foo {
use A;
use B;
public constructor(int id, string name) {
A.constructor(id);
B.constructor(name);
}
}
Asi nerozumím té otázce. Je to otázka po syntaxi, sémantice, runtime? Všechno je možný - můžu inicializovat aspektem, anotací...
Syntaxe.
Jak tyto vlastnosti inicializovat, případně když ta inicializace má nějakou komplexní logiku. Proč by to měl být problém souvisí poněkud s tím, že ty fieldy z traitu jsou privátní, mají nějaký provázaný stav, který by si měl hlídat ten trait.
Jo, jestli jde o syntax, líbí se mi to jak to uvádíš výše. Všechnu logiku bych dal do konstruktorů jako programový kód, IMHO to je nejčitelnější. Co se týče chování, nedělat bych tam žádnou automagii, to se vyplatí až při násobném použité té magie. Co se týče čitelnosti traitu a srozumitelnosti z čeho je výsledný objekt poskládaný, tak podle mě mají traity smysl právě tehdy, když je nemusím moc číst. Já mám traity třeba WithLogger, WithImages, WithRelations apod. kde právě dělám kompozici. Ten trait přidává jednu jednoduchou pochopitelnou vlastnost (logger, obrázky...). Výhoda je samosebou znovupoužitelnost spojená s flexibilitou. Takže pokud mám nějaký objekt a k němu chci obrázky, tak jen připojím trait. Přidám jedno slovo a je hotovo. Razantně lepší než dědičnost, citelně lepší než kompozice. Pokud pak v objektu intenzivně metody traitu používám a chci jeho chování zase odstranit, stačí trait odpojit a opravit chyby kompilátoru. Zase lepší než dědičnost a srovnatelné s kompozicí.
-
...
Díky za příspěvek.
-
V první otázce zní: Nezneužívat dědičnost, radši na to vzít traity. Já říkám: Ale já vidím kompozici, k té traity nepotřebuju. Odpověď: V kontextu OOP je to jinak. Tak jak je to? Co je trait?
Abych nebyl za kverulanta, já bych prostě inicializoval v konstruktoru, kde bych volal konstruktor traitu. Nebo je myšlena nějaká automatická inicializace? Asi nerozumím té otázce. Je to otázka po syntaxi, sémantice, runtime? Všechno je možný - můžu inicializovat aspektem, anotací...
Také nevidím smysl traitů, kompozice se mi jeví jako přehlednější. Když ji injektuji do konstruktoru, mohu bohatě využít polymorfismu, což u traity není možné. Například logger je takto jednodušší než přes traitu - mohu ho z vnějšku vyměnit nebo zaslepit, a to pro každou instanci zvlášť.
-
Souhlas, že traity a DI jsou částečně zastupitelné přístupy. Vhodnost jednoho či druhého záleží IMHO na okolnostech.
-
Souhlas, že traity a DI jsou částečně zastupitelné přístupy. Vhodnost jednoho či druhého záleží IMHO na okolnostech.
Nemohu souhlasit. Tyto dva koncepty spolu nijak nesouvisí. Traity jsou o lepení kódu. DI je o přiznání závislostí. Nebe a dudy.
-
Souhlas, že traity a DI jsou částečně zastupitelné přístupy. Vhodnost jednoho či druhého záleží IMHO na okolnostech.
Nebe a dudy.
Tak.
-
Souhlas, že traity a DI jsou částečně zastupitelné přístupy. Vhodnost jednoho či druhého záleží IMHO na okolnostech.
Nemohu souhlasit. Tyto dva koncepty spolu nijak nesouvisí. Traity jsou o lepení kódu. DI je o přiznání závislostí. Nebe a dudy.
Souhlasim, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
-
Souhlas, že traity a DI jsou částečně zastupitelné přístupy. Vhodnost jednoho či druhého záleží IMHO na okolnostech.
Nemohu souhlasit. Tyto dva koncepty spolu nijak nesouvisí. Traity jsou o lepení kódu. DI je o přiznání závislostí. Nebe a dudy.
Souhlasim, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
U traitu je ta závislost vnitřní, u DI vnější.
-
im, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
Podle mě ses zaměřil na obecný význam slova "závislost", ale ne na skutečnou funkci DI třeba v tom konstruktoru. Trait řeší chování celé třídy (typu), DI rozhoduje o situaci či chování konkrétní instance.
-
class C(val f: Integer) extends T {
def printF(): Unit = {
println(f)
}
}
Tohle je docela hezký.
Jde nějak ještě když bych tomu chtěl přidat nějakou logiku? Tedy konstruktor přijme f, přepočítá ho, a teprve výsledek uloží do fieldu f?
Dotty (Scala 3) podporuje parametrizované traity. (A také "intersection types", které mohou při práci s traity přijít vhod.)
trait Polite(text: String) {
val greeting = init(text)
def greet(name: String) = s"$greeting $name!"
private def init(s: String) = s"${text.toUpperCase},"
}
trait Curious(val question: String)
class MessageStyle(g: String) extends Polite(g) with Curious("How are you?")
def composeMessage(data: Polite & Curious, name: String): String = {
s"${data.greet(name)}\n${data.question}"
}
object Main extends App {
val messageStyle = MessageStyle("hello")
println(composeMessage(messageStyle, "World"))
}
(https://scastie.scala-lang.org/VCcgilMpRMWpnZ773wMJIw)
-
im, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
Podle mě ses zaměřil na obecný význam slova "závislost", ale ne na skutečnou funkci DI třeba v tom konstruktoru. Trait řeší chování celé třídy (typu), DI rozhoduje o situaci či chování konkrétní instance.
Přesně. Navíc DI je zpravidla runtime kdežto traity compile time. Někdy potřebujeme to a jindy ono.
-
im, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
Podle mě ses zaměřil na obecný význam slova "závislost", ale ne na skutečnou funkci DI třeba v tom konstruktoru. Trait řeší chování celé třídy (typu), DI rozhoduje o situaci či chování konkrétní instance.
Přesně. Navíc DI je zpravidla runtime kdežto traity compile time. Někdy potřebujeme to a jindy ono.
Me slo o pojem "priznani zavislosti". S durazem na priznani. Prijde mi to, ze to neprimo znamena u traitu zavislost neni, nebo ze neni videt. Coz je podle me zavadejici. DI je o tom, ze si nemusim vyrabet nastroj kterym neco udelam, ale nekdo mi ho doda. Ale musim vedet jak to pouzit. O traitu toho ja moc vedet nemusim, protoze ja ho nemusim pouzivat, ale v compile time na nej stejne deklaruju zavislost.
-
im, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
Podle mě ses zaměřil na obecný význam slova "závislost", ale ne na skutečnou funkci DI třeba v tom konstruktoru. Trait řeší chování celé třídy (typu), DI rozhoduje o situaci či chování konkrétní instance.
Přesně. Navíc DI je zpravidla runtime kdežto traity compile time. Někdy potřebujeme to a jindy ono.
Me slo o pojem "priznani zavislosti". S durazem na priznani. Prijde mi to, ze to neprimo znamena u traitu zavislost neni, nebo ze neni videt. Coz je podle me zavadejici. DI je o tom, ze si nemusim vyrabet nastroj kterym neco udelam, ale nekdo mi ho doda. Ale musim vedet jak to pouzit. O traitu toho ja moc vedet nemusim, protoze ja ho nemusim pouzivat, ale v compile time na nej stejne deklaruju zavislost.
Trait souvisí s DI asi stejně jako souvisí s DI funkce str_concat() v následujícím kódu:
class Foo {
string format(s : string) : string {
return str_concat("[", s, "]")
}
}
Je to závislost? Je. Je přiznaná či nepřiznaná? Eee... Mluvil by někdo normální o tom jako o DI?
-
Dotty (Scala 3) podporuje parametrizované traity. (A také "intersection types", které mohou při práci s traity přijít vhod.)
trait Polite(text: String) {
val greeting = init(text)
def greet(name: String) = s"$greeting $name!"
private def init(s: String) = s"${text.toUpperCase},"
}
trait Curious(val question: String)
class MessageStyle(g: String) extends Polite(g) with Curious("How are you?")
def composeMessage(data: Polite & Curious, name: String): String = {
s"${data.greet(name)}\n${data.question}"
}
object Main extends App {
val messageStyle = MessageStyle("hello")
println(composeMessage(messageStyle, "World"))
}
(https://scastie.scala-lang.org/VCcgilMpRMWpnZ773wMJIw)
Hezký.
Žel, opět se musím zeptat: Jde nějak ještě když bych tomu chtěl přidat nějakou logiku? Tedy konstruktor MessageStyle přijme g, přepočítá ho, a teprve výsledek uloží do fieldu Polite(g).
-
Žel, opět se musím zeptat: Jde nějak ještě když bych tomu chtěl přidat nějakou logiku? Tedy konstruktor MessageStyle přijme g, přepočítá ho, a teprve výsledek uloží do fieldu Polite(g).
Určitě. Pokud ta logika nemůže být až v traitu (metoda init v původním příkladu), dá se v argumentu traitu použít libovolný výraz (typicky funkce, metoda v přidruženém objektu, jednoduchý inline výraz).
trait T(val traitField: String)
def prepareArgumentForTrait(l: List[String]): String = l.mkString("")
class C(l: List[String]) extends T(prepareArgumentForTrait(l))
object Main extends App {
val o = C(List("a", "b", "c"))
println(o.traitField)
}
https://scastie.scala-lang.org/y9HBofuwRce6a37fWbXdpA
-
...
Díky za příspěvek.
-
im, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
Podle mě ses zaměřil na obecný význam slova "závislost", ale ne na skutečnou funkci DI třeba v tom konstruktoru. Trait řeší chování celé třídy (typu), DI rozhoduje o situaci či chování konkrétní instance.
Přesně. Navíc DI je zpravidla runtime kdežto traity compile time. Někdy potřebujeme to a jindy ono.
Me slo o pojem "priznani zavislosti". S durazem na priznani. Prijde mi to, ze to neprimo znamena u traitu zavislost neni, nebo ze neni videt. Coz je podle me zavadejici. DI je o tom, ze si nemusim vyrabet nastroj kterym neco udelam, ale nekdo mi ho doda. Ale musim vedet jak to pouzit. O traitu toho ja moc vedet nemusim, protoze ja ho nemusim pouzivat, ale v compile time na nej stejne deklaruju zavislost.
Trait souvisí s DI asi stejně jako souvisí s DI funkce str_concat() v následujícím kódu:
class Foo {
string format(s : string) : string {
return str_concat("[", s, "]")
}
}
Je to závislost? Je. Je přiznaná či nepřiznaná? Eee... Mluvil by někdo normální o tom jako o DI?
Nemam pocit, ze bych nekde psal, ze trait souvisi s DI.
Jen se ohrazuju proti tvrzeni ze DI je o priznani zavislosti.
Pripad bez DI a bez traitu:
Potrebuju zatlouct hrebik... vyrobim si kladivo.
DI:
Potrebuju zatlouct hrebik... podej mi kladivo
Trait:
Potrebuju zatlouct hrebik... ja jsem mimo jine taky kladivo.
Vsude mam zavislost na kladivu. V prvnim a tretim pripade mam zavislost dokonce na konkretni implementaci. S DI se nekdo muze rozhodnout v runtimu jaky kladivo dostanu a zavisim jen na interfacu.
Z kontextu predpokladam, ze se bavime o "dependency injection" a ne o "dependency inversion".
-
Nemam pocit, ze bych nekde psal, ze trait souvisi s DI.
V poho. Reagoval jsem na celé vlákno. Netušil jsem, že tuhle blbost někomu bude stát za to rozvíjet.
im, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
Podle mě ses zaměřil na obecný význam slova "závislost", ale ne na skutečnou funkci DI třeba v tom konstruktoru. Trait řeší chování celé třídy (typu), DI rozhoduje o situaci či chování konkrétní instance.
Přesně. Navíc DI je zpravidla runtime kdežto traity compile time. Někdy potřebujeme to a jindy ono.
Me slo o pojem "priznani zavislosti". S durazem na priznani. Prijde mi to, ze to neprimo znamena u traitu zavislost neni, nebo ze neni videt. Coz je podle me zavadejici. DI je o tom, ze si nemusim vyrabet nastroj kterym neco udelam, ale nekdo mi ho doda. Ale musim vedet jak to pouzit. O traitu toho ja moc vedet nemusim, protoze ja ho nemusim pouzivat, ale v compile time na nej stejne deklaruju zavislost.
Trait souvisí s DI asi stejně jako souvisí s DI funkce str_concat() v následujícím kódu:
class Foo {
string format(s : string) : string {
return str_concat("[", s, "]")
}
}
Je to závislost? Je. Je přiznaná či nepřiznaná? Eee... Mluvil by někdo normální o tom jako o DI?
Nemam pocit, ze bych nekde psal, ze trait souvisi s DI.
Jen se ohrazuju proti tvrzeni ze DI je o priznani zavislosti.
Pripad bez DI a bez traitu:
Potrebuju zatlouct hrebik... vyrobim si kladivo.
DI:
Potrebuju zatlouct hrebik... podej mi kladivo
Trait:
Potrebuju zatlouct hrebik... ja jsem mimo jine taky kladivo.
Vsude mam zavislost na kladivu. V prvnim a tretim pripade mam zavislost dokonce na konkretni implementaci. S DI se nekdo muze rozhodnout v runtimu jaky kladivo dostanu a zavisim jen na interfacu.
Z kontextu predpokladam, ze se bavime o "dependency injection" a ne o "dependency inversion".
Řekl bych, že takto to není. Trvám na tom, že DI (dependency injection) je o přiznání závislostí.
DI: abych mohl fungovat, dej mi kladivo
neDI: budu fungovat, kladivo si seženu
to je celé, víc v tom není.
Trait je úplně něco jiného. DI může respektovat, stejně jako nemusí.
-
Nemam pocit, ze bych nekde psal, ze trait souvisi s DI.
V poho. Reagoval jsem na celé vlákno. Netušil jsem, že tuhle blbost někomu bude stát za to rozvíjet.
im, ze je tam rozdil, ale nevidim ze by u toho traitu ta zavislost byla mene priznana.
Podle mě ses zaměřil na obecný význam slova "závislost", ale ne na skutečnou funkci DI třeba v tom konstruktoru. Trait řeší chování celé třídy (typu), DI rozhoduje o situaci či chování konkrétní instance.
Přesně. Navíc DI je zpravidla runtime kdežto traity compile time. Někdy potřebujeme to a jindy ono.
Me slo o pojem "priznani zavislosti". S durazem na priznani. Prijde mi to, ze to neprimo znamena u traitu zavislost neni, nebo ze neni videt. Coz je podle me zavadejici. DI je o tom, ze si nemusim vyrabet nastroj kterym neco udelam, ale nekdo mi ho doda. Ale musim vedet jak to pouzit. O traitu toho ja moc vedet nemusim, protoze ja ho nemusim pouzivat, ale v compile time na nej stejne deklaruju zavislost.
Trait souvisí s DI asi stejně jako souvisí s DI funkce str_concat() v následujícím kódu:
class Foo {
string format(s : string) : string {
return str_concat("[", s, "]")
}
}
Je to závislost? Je. Je přiznaná či nepřiznaná? Eee... Mluvil by někdo normální o tom jako o DI?
Nemam pocit, ze bych nekde psal, ze trait souvisi s DI.
Jen se ohrazuju proti tvrzeni ze DI je o priznani zavislosti.
Pripad bez DI a bez traitu:
Potrebuju zatlouct hrebik... vyrobim si kladivo.
DI:
Potrebuju zatlouct hrebik... podej mi kladivo
Trait:
Potrebuju zatlouct hrebik... ja jsem mimo jine taky kladivo.
Vsude mam zavislost na kladivu. V prvnim a tretim pripade mam zavislost dokonce na konkretni implementaci. S DI se nekdo muze rozhodnout v runtimu jaky kladivo dostanu a zavisim jen na interfacu.
Z kontextu predpokladam, ze se bavime o "dependency injection" a ne o "dependency inversion".
Řekl bych, že takto to není. Trvám na tom, že DI (dependency injection) je o přiznání závislostí.
DI: abych mohl fungovat, dej mi kladivo
neDI: budu fungovat, kladivo si seženu
to je celé, víc v tom není.
Trait je úplně něco jiného. DI může respektovat, stejně jako nemusí.
Chapu. Ty mluvis o zavislosti ma dodavatelich kladiv a ne na kladivech.
Potom ano....
Ja si prekladam dependency injection jako injektaz zavislosti (kladivo) ne jako zavisla injektaz (dodavatel) to by potom spis byla dependent injection.
Mirnou oklikou zpet.... Nebylo by treba hezci aby ten koho obohacuju traitem o tom vubec nemusel vedet?
-
Mirnou oklikou zpet.... Nebylo by treba hezci aby ten koho obohacuju traitem o tom vubec nemusel vedet?
Beru zpet, protoze vlastne nevim jak to udelat.... To co sem myslel nefunguje tak jak sem myslel...
-
Mirnou oklikou zpet.... Nebylo by treba hezci aby ten koho obohacuju traitem o tom vubec nemusel vedet?
Beru zpet, protoze vlastne nevim jak to udelat.... To co sem myslel nefunguje tak jak sem myslel...
Nesplňuje to dědičnost nebo dekorátor?
-
Mirnou oklikou zpet.... Nebylo by treba hezci aby ten koho obohacuju traitem o tom vubec nemusel vedet?
Beru zpet, protoze vlastne nevim jak to udelat.... To co sem myslel nefunguje tak jak sem myslel...
Nesplňuje to dědičnost nebo dekorátor?
Ne.
Tam zase ten kdo rozsiruje nebo dekoruje musi vedet koho rozsiruje nebo dekoruje.
To neni ono.
Mozna by to nejak slo, ale uz se mi nechce premyslet. A stejne pro to nemam asi prakticke vyuziti.
Trivialni idea je, ze mam treba nejakou mapu kde klice jsou nejaky jmena a hodnoty jsou treba funkce nebo ... hodnoty.
Typ je externe definovan (clojure/spec napr.)
A pak budu mit nejaky "trait/dekorator/neco..." ktery teda bude vedet, ze ma okraslovat nejakou mapu, ale uz nemusi znat co v te mape je. A prida svoji funkcnost do mapy associaci a rozsireni typu do externi definice.
A tady koncim, protoze nejak nevim jak takou "vygenerovanou" specifikaci typu pouzit jako treba parametr funkce.
Napadaji me jen samy vosklivosti.
-
Mirnou oklikou zpet.... Nebylo by treba hezci aby ten koho obohacuju traitem o tom vubec nemusel vedet?
Beru zpet, protoze vlastne nevim jak to udelat.... To co sem myslel nefunguje tak jak sem myslel...
Přidávání čí změnu fieldů, metod, anotací či přidání implementací u třídy, ke které nemám zdroják, některé systémy umí. Třeba BrightspotCMD postavené nad Dari umí tzv. Modifications, Augmentations, Substitutions a Alterations https://docs.brightspot.com/4.2/en/dari-guide/data-modeling/modifications.html Ta třída o své úpravě neví a runtime jí nahradí jinou implementací. Je to implementované v rámci té datové persistence v Dari. Určitě existují další pokusy o totéž, například v rámci runtime weavingu. Používá se to poměrně dobře, ale je to pořád jen náhražka. Daleko lepší by bylo, pokud by to bylo součástí jazyka nebo standardního runtime.
-
Dotty (Scala 3) podporuje parametrizované traity. (A také "intersection types", které mohou při práci s traity přijít vhod.)
Hmm, jaký pak zbývá rozdíl mezi trait a class kromě toho, že není možné dědit z více class najednou? Co by se stalo, kdyby se klíčové slovo class zrušilo a používaly se jen tyhle nové traity?
-
Dotty (Scala 3) podporuje parametrizované traity. (A také "intersection types", které mohou při práci s traity přijít vhod.)
Hmm, jaký pak zbývá rozdíl mezi trait a class kromě toho, že není možné dědit z více class najednou? Co by se stalo, kdyby se klíčové slovo class zrušilo a používaly se jen tyhle nové traity?
Nevím jak Dotty, ale základní rozdíl mezi dědičností a traity je v té dědičnosti. Když máš objekt O, do kterého přidáš trait T, tak ten objekt O není tím T. (Maximálně tak T obsahuje.) Zatímco když O dědí od předka P, tak O je P.
Jako asi pro tebe nic nového, ale tohle je prostě ten rozdíl 1. To je všechno.
1/ Tak maximálně ještě, že metody z traitu se obvykle nepřetěžují, že se s tím trochu jinak pracuje, a tak.
-
Dotty (Scala 3) podporuje parametrizované traity. (A také "intersection types", které mohou při práci s traity přijít vhod.)
Hmm, jaký pak zbývá rozdíl mezi trait a class kromě toho, že není možné dědit z více class najednou? Co by se stalo, kdyby se klíčové slovo class zrušilo a používaly se jen tyhle nové traity?
Nevím jak Dotty, ale základní rozdíl mezi dědičností a traity je v té dědičnosti. Když máš objekt O, do kterého přidáš trait T, tak ten objekt O není tím T. (Maximálně tak T obsahuje.) Zatímco když O dědí od předka P, tak O je P.
Jako asi pro tebe nic nového, ale tohle je prostě ten rozdíl 1. To je všechno.
1/ Tak maximálně ještě, že metody z traitu se obvykle nepřetěžují, že se s tím trochu jinak pracuje, a tak.
To je IMHO o detailech, v některých jazycích jsou traity v podstatě rozhraní s možností implementace (některých metod). Takto to dává docela smysl v praxi, akorát tvoji definici dědičnosti to (bohužel?) splňuje. Taky to je dobře sehrané s generickými typy.
-
Líbí se mi koncept traitů (v Rustu, ve Scale jsem je používal je jako metodu pro vytvoření partial classes), mají tam velkou roli na tom jak jazyk funguje, ale po tom, co jsem viděl na tomto vlákně, musím říci, že něco na tom Golangu bude ;).
-
něco na tom Golangu bude
Bude, hlavně od verze Go 2, která má dostat koncepty.
-
Dotty (Scala 3) podporuje parametrizované traity. (A také "intersection types", které mohou při práci s traity přijít vhod.)
Hmm, jaký pak zbývá rozdíl mezi trait a class kromě toho, že není možné dědit z více class najednou? Co by se stalo, kdyby se klíčové slovo class zrušilo a používaly se jen tyhle nové traity?
Nevím jak Dotty, ale základní rozdíl mezi dědičností a traity je v té dědičnosti. Když máš objekt O, do kterého přidáš trait T, tak ten objekt O není tím T. (Maximálně tak T obsahuje.) Zatímco když O dědí od předka P, tak O je P.
Jako asi pro tebe nic nového, ale tohle je prostě ten rozdíl 1. To je všechno.
1/ Tak maximálně ještě, že metody z traitu se obvykle nepřetěžují, že se s tím trochu jinak pracuje, a tak.
Mě to zajímá právě v Dotty, jestli tam mohou traity mít parametry při instanciaci, ptám se po rozdílu mezi trait a class, to byla tak poslední věc co class uměla a trait ne. Možná už to budou opravdu jen detaily - Java interop nebo tak, možná mi něco nedochází.
Ve Scale (i pre-Dotty) je totiž možné udělat tohle:
trait Foo {
def hello(): Unit = {println("Hello, world")}
}
object Main {
def useFoo(foo: Foo) {
foo.hello()
}
def main(args: Array[String]) = {
val foo = new Foo {};
useFoo(foo)
}
}
V tomhle kontextu mi přijde, že i tvé rozlišení v tom, že class znamená "být" a trait znamená "mít" se smývá, protože pokud něco jsem, tak to i mám, "mít" je silnější.
-
něco na tom Golangu bude
Bude, hlavně od verze Go 2, která má dostat koncepty.
Koncepty? Trochu nechápu.
Go chybí dle mě: Generika, pořádný sestavovací/balíkovací systém, traity, podmínky jako výrazy jsou v moderních jazycích podmínkou, ne?
Navíc, jak uděláte toto v Go?
struct Point {
x: i32,
y: i32,
}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
---
Navíc trait má popisovat nějaké chování, funkce, neměl by obsahovat data.
-
něco na tom Golangu bude
Bude, hlavně od verze Go 2, která má dostat koncepty.
Koncepty? Trochu nechápu.
Konepty jako v C++ aka bounded types. Už je preview.
-
Navíc trait má popisovat nějaké chování, funkce, neměl by obsahovat data.
Hele, takhle uvažovat nemůžeš. V jazycích jako je Java, C#, PHP jsou class to, co je v Haskellu type. To co je v Haskellu class je v Java interface... Takže prohlašovat, že v traitu něco být nemá, je takové nepraktické. V zadání bylo co tam bylo. Neupravujme ho.
-
V tomhle kontextu mi přijde, že i tvé rozlišení v tom, že class znamená "být" a trait znamená "mít" se smývá, protože pokud něco jsem, tak to i mám, "mít" je silnější.
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
-
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Takže ve skutečnosti chceš násobnou dědičnost v jazyku, který ji nemá?
-
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Takže ve skutečnosti chceš násobnou dědičnost v jazyku, který ji nemá?
Lze dědit tak, aby potomek nebyl stejného typu jako předek?
+ Tak nějak očekávám a považuji za výhodu, že tu získanou vlastnost nemůžu přetěžovat. Ale zde mám málo zkušeností, nakolik je to podstatná výhoda.
-
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Takže ve skutečnosti chceš násobnou dědičnost v jazyku, který ji nemá?
Lze dědit tak, aby potomek nebyl stejného typu jako předek?
To nejde, ale proč by to mělo vadit?
-
Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Můžeš chybějící vlastnosti také injektovat.
-
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Takže ve skutečnosti chceš násobnou dědičnost v jazyku, který ji nemá?
Lze dědit tak, aby potomek nebyl stejného typu jako předek?
To nejde, ale proč by to mělo vadit?
To snad ani nebudu rozvádět.
Každopádně pokud to nejde, tak to budiž odpovědí pro @Ink
-
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Takže ve skutečnosti chceš násobnou dědičnost v jazyku, který ji nemá?
Lze dědit tak, aby potomek nebyl stejného typu jako předek?
To nejde, ale proč by to mělo vadit?
To snad ani nebudu rozvádět.
Každopádně pokud to nejde, tak to budiž odpovědí pro @Ink
Trait je zobecnění rozhraní, tak to ber tak, že to je stejná "dědičnost" jako implementace rozhraní.
-
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Takže ve skutečnosti chceš násobnou dědičnost v jazyku, který ji nemá?
Lze dědit tak, aby potomek nebyl stejného typu jako předek?
To nejde, ale proč by to mělo vadit?
To snad ani nebudu rozvádět.
Každopádně pokud to nejde, tak to budiž odpovědí pro @Ink
Trait je zobecnění rozhraní, tak to ber tak, že to je stejná "dědičnost" jako implementace rozhraní.
To nedává smysl. Já nemám zájem o zobecněné rozhraní. Já nemám zájem o vynucenou dědičnost (rozhraní přináší do typu zařazení do kategorie, to nemusím chtít). Nevím, proč bych to tak měl brát.
Pokud mé chápání výrazu "trait" je posunuté, budiž, to je samozřejmě možné. V tom případě si v mé otázce to slovo škrtni a nech tam toto: Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
-
No samozřejmě. Problém je v tom, že se na to díváš z druhé strany. Já chci do objektu přidat chování a atributy, ale nechci, aby se mi tím změnil typ například. Tedy chci aby zůstalo "mít", ale nezměnilo se "být".
Usecase, které pro traity mám (a které se samozřejmě může lišit jazyk od jazyka):
Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Takže ve skutečnosti chceš násobnou dědičnost v jazyku, který ji nemá?
Lze dědit tak, aby potomek nebyl stejného typu jako předek?
To nejde, ale proč by to mělo vadit?
To snad ani nebudu rozvádět.
Každopádně pokud to nejde, tak to budiž odpovědí pro @Ink
Trait je zobecnění rozhraní, tak to ber tak, že to je stejná "dědičnost" jako implementace rozhraní.
To nedává smysl. Já nemám zájem o zobecněné rozhraní. Já nemám zájem o vynucenou dědičnost (rozhraní přináší do typu zařazení do kategorie, to nemusím chtít). Nevím, proč bych to tak měl brát.
Pokud mé chápání výrazu "trait" je posunuté, budiž, to je samozřejmě možné. V tom případě si v mé otázce to slovo škrtni a nech tam toto: Mám nějaký objekt. Chci, aby tento objekt měl určité vlastnosti. Buď tam ty vlastnosti dopíšu, nebo je "přidám" pomocí traitu (protože stejné chování jsem dělal jinde). Přičemž vlastnostmi je jak chování (vlastní nějaké metody), tak i data (vlastní nějaké atributy), tak i kategorie (objekt implementuje nějaké rozhraní). A samozřejmě nechci být omezován, takže mohu přidávat kteroukoliv z těchto tří vlastností - ne jak je to u dědičnosti.
Moc to komplikuješ, tohle je jako chtít auto s hranatýma kolama, co nedrncá.
-
Moc to komplikuješ, tohle je jako chtít auto s hranatýma kolama, co nedrncá.
Ale houby. Traity se tak jak je popisuju normálně používají. Takže to není můj výmysl. Jen tu @Ink uvažoval nad tím, zda to co popisuju není obyčejná dědičnost. Není. C'est tout.
-
Moc to komplikuješ, tohle je jako chtít auto s hranatýma kolama, co nedrncá.
Ale houby. Traity se tak jak je popisuju normálně používají. Takže to není můj výmysl. Jen tu @Ink uvažoval nad tím, zda to co popisuju není obyčejná dědičnost. Není. C'est tout.
No ale to bys musel fakt přijít s nějakým legitimním vysvětlením, ne že "nechceš", aby to byla dědičnost nebo aby se ten objekt zařadil do kategorie. Ty tady filosofuješ jak Fromm, na druhé straně argumentuješ, že "se to dělá". Oboje beru, ale přijde mi, že interface, trait, mixin a předek jsou do určité míry překrývající se koncepty a v zásadě abstraktní třída a násobná dědičnost to všechno úplně v pohodě řeší.
Jsou jazyky bez tříd, jako je třeba Rust se svými traity navlečenými na struktury a taky to funguje - nepotřebuješ tam skládat data a metody přes traity, něco málo by to zjednodušilo, ale žádný velký průlom v tom nevidím.
A Ty jsi přišel s tím, že chceš něco mezi a (z technického hlediska) nevidím důvod, na jedné straně číhá Fromm a na druhé jazyky, které nikdy nemají dost a přidávají další a další způsoby, jak udělat to, co už dostatečně dobře umí. Nebo něco nechápu, to je klidně možné.
-
Moc to komplikuješ, tohle je jako chtít auto s hranatýma kolama, co nedrncá.
Ale houby. Traity se tak jak je popisuju normálně používají. Takže to není můj výmysl. Jen tu @Ink uvažoval nad tím, zda to co popisuju není obyčejná dědičnost. Není. C'est tout.
No ale to bys musel fakt přijít s nějakým legitimním vysvětlením, ne že "nechceš", aby to byla dědičnost nebo aby se ten objekt zařadil do kategorie. Ty tady filosofuješ jak Fromm, na druhé straně argumentuješ, že "se to dělá". Oboje beru, ale přijde mi, že interface, trait, mixin a předek jsou do určité míry překrývající se koncepty a v zásadě abstraktní třída a násobná dědičnost to všechno úplně v pohodě řeší.
Jsou jazyky bez tříd, jako je třeba Rust se svými traity navlečenými na struktury a taky to funguje - nepotřebuješ tam skládat data a metody přes traity, něco málo by to zjednodušilo, ale žádný velký průlom v tom nevidím.
A Ty jsi přišel s tím, že chceš něco mezi a (z technického hlediska) nevidím důvod, na jedné straně číhá Fromm a na druhé jazyky, které nikdy nemají dost a přidávají další a další způsoby, jak udělat to, co už dostatečně dobře umí. Nebo něco nechápu, to je klidně možné.
Jak jsem tu již zmiňoval, tak v Rustu jsou traity a jejich implementace pro typ/strukturu hodně mocné.
-
Moc to komplikuješ, tohle je jako chtít auto s hranatýma kolama, co nedrncá.
Ale houby. Traity se tak jak je popisuju normálně používají. Takže to není můj výmysl. Jen tu @Ink uvažoval nad tím, zda to co popisuju není obyčejná dědičnost. Není. C'est tout.
No ale to bys musel fakt přijít s nějakým legitimním vysvětlením, ne že "nechceš", aby to byla dědičnost nebo aby se ten objekt zařadil do kategorie. Ty tady filosofuješ jak Fromm, na druhé straně argumentuješ, že "se to dělá". Oboje beru, ale přijde mi, že interface, trait, mixin a předek jsou do určité míry překrývající se koncepty a v zásadě abstraktní třída a násobná dědičnost to všechno úplně v pohodě řeší.
Jsou jazyky bez tříd, jako je třeba Rust se svými traity navlečenými na struktury a taky to funguje - nepotřebuješ tam skládat data a metody přes traity, něco málo by to zjednodušilo, ale žádný velký průlom v tom nevidím.
A Ty jsi přišel s tím, že chceš něco mezi a (z technického hlediska) nevidím důvod, na jedné straně číhá Fromm a na druhé jazyky, které nikdy nemají dost a přidávají další a další způsoby, jak udělat to, co už dostatečně dobře umí. Nebo něco nechápu, to je klidně možné.
Já se obávám, že přístup: "když to nebudeš chtít, tak to nebudeš potřebovat" mi tak docela nevyhovuje. Jako třeba ti to jen nedochází, neříkám nic, ale nevidím v tom přínos to nějak dál rozpatlávat.
Díky za příspěvky.
-
Jak jsem tu již zmiňoval, tak v Rustu jsou traity a jejich implementace pro typ/strukturu hodně mocné.
Rust je skvělej. Jen to, jak má řešený traity se krom názvu ničím nepodobá mému zadání. (Pokud jsem se ošklivě nepřehlédl.)
-
Já v Rustu (neinicalizuji hodnoty traitu, to ani nejde) prostě udělám každé struktuře funkci new. Pokud by to nebyl v tom fiktivním jazyce (který záhadně připomíná scalu) problém, tak bych do traitu dal funkci new, z třídy "obsahující" trait bych zavolal funkci new z A a funkci new z B. Nebo něco na ten způsob.
-
Já v Rustu (neinicalizuji hodnoty traitu, to ani nejde) prostě udělám každé struktuře funkci new. Pokud by to nebyl v tom fiktivním jazyce (který záhadně připomíná scalu) problém, tak bych do traitu dal funkci new, z třídy "obsahující" trait bych zavolal funkci new z A a funkci new z B. Nebo něco na ten způsob.
Pochopil jsem. Díky. Je to cca to první řešení, které mě napadlo. Jen jsem si dělal naděje, že to třeba jde i jinak a líp :-) Znáš to, líná huba...
-
....................................
Já se obávám, že přístup: "když to nebudeš chtít, tak to nebudeš potřebovat" mi tak docela nevyhovuje. Jako třeba ti to jen nedochází, neříkám nic, ale nevidím v tom přínos to nějak dál rozpatlávat.
Díky za příspěvky.
když je pro páníčka vobyčejná dědičnost moc vobyčejná tak ať si metody z voběktu do voběktu kromě zamě hezky kopíruje nějakým skriptem a bude to jako dědičnost bez toho aby byl voběkt potomkem rodiče :P :P ;D ;D ;) ;)