Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: BoneFlute 18. 12. 2020, 00:25:06

Název: Trait a konstruktor
Přispěvatel: 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:

Kód: [Vybrat]
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 18. 12. 2020, 00:32:37
Mě napadají dvě řešení:

Kód: [Vybrat]
class Foo {
    use A;
    use B;
    public constructor(int id, string name) {
        A.constructor(id);
        B.constructor(name);
    }
}

nebo odvážnější:

Kód: [Vybrat]
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);
    }

}
Název: Re:Trait a konstruktor
Přispěvatel: Ink 18. 12. 2020, 09:59:42
V Rustu, pokud vím, trait nemá fieldy. Proč je tam potřebuješ mít, patří tam vůbec?
Název: Re:Trait a konstruktor
Přispěvatel: okalousek 18. 12. 2020, 10:07:56
V Rustu, pokud vím, trait nemá fieldy. Proč je tam potřebuješ mít, patří tam vůbec?
Ve Scale ano.
Název: Re:Trait a konstruktor
Přispěvatel: registrovany_ava 18. 12. 2020, 10:36:14
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)
  }
}
Název: Re:Trait a konstruktor
Přispěvatel: listoper 18. 12. 2020, 14:03:34
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:

Kód: [Vybrat]
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.
Název: Re:Trait a konstruktor
Přispěvatel: Idris 18. 12. 2020, 14:26:42
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 :)
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 18. 12. 2020, 19:08:12
Co se týče námitky, zda do traitů patří data, a tak.

V jednom z mejch DSL mám něco takového:

Kód: [Vybrat]
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?
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 18. 12. 2020, 19:13:32
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 18. 12. 2020, 19:17:35
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?
Název: Re:Trait a konstruktor
Přispěvatel: Idris 18. 12. 2020, 19:18:39
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?
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 18. 12. 2020, 19:43:44
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.
Název: Re:Trait a konstruktor
Přispěvatel: Idris 18. 12. 2020, 20:23:27
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í.
Název: Re:Trait a konstruktor
Přispěvatel: Ondrej Nemecek 18. 12. 2020, 20:45:10
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
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 18. 12. 2020, 22:44:38
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:

Kód: [Vybrat]
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.
Název: Re:Trait a konstruktor
Přispěvatel: Ondrej Nemecek 19. 12. 2020, 01:34:00
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í...
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 19. 12. 2020, 01:44:11
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?:
Kód: [Vybrat]
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.
Název: Re:Trait a konstruktor
Přispěvatel: registrovany_ava 19. 12. 2020, 08:15:18
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ší.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 19. 12. 2020, 17:00:53
... 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.
Název: Re:Trait a konstruktor
Přispěvatel: Ondrej Nemecek 20. 12. 2020, 01:34:06
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?:
Kód: [Vybrat]
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í.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 20. 12. 2020, 02:33:33
...
Díky za příspěvek.
Název: Re:Trait a konstruktor
Přispěvatel: Kit 20. 12. 2020, 19:45:28
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ášť.
Název: Re:Trait a konstruktor
Přispěvatel: Ondrej Nemecek 20. 12. 2020, 22:07:52
Souhlas, že traity a DI jsou částečně zastupitelné přístupy. Vhodnost jednoho či druhého záleží IMHO na okolnostech.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 20. 12. 2020, 23:09:07
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.
Název: Re:Trait a konstruktor
Přispěvatel: Idris 20. 12. 2020, 23:53:01
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.
Název: Re:Trait a konstruktor
Přispěvatel: listoper 21. 12. 2020, 08:20:40
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.
Název: Re:Trait a konstruktor
Přispěvatel: Kit 21. 12. 2020, 09:48:48
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ší.
Název: Re:Trait a konstruktor
Přispěvatel: Ink 21. 12. 2020, 09:52:04
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.
Název: Re:Trait a konstruktor
Přispěvatel: Jaroslav Havlín 21. 12. 2020, 10:33:09
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.)

Kód: [Vybrat]
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)
Název: Re:Trait a konstruktor
Přispěvatel: Ondrej Nemecek 21. 12. 2020, 15:10:59
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.
Název: Re:Trait a konstruktor
Přispěvatel: listoper 21. 12. 2020, 16:56:19
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 21. 12. 2020, 17:55:09
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:
Kód: [Vybrat]
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?
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 21. 12. 2020, 18:14:02
Dotty (Scala 3) podporuje parametrizované traity. (A také "intersection types", které mohou při práci s traity přijít vhod.)

Kód: [Vybrat]
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).
Název: Re:Trait a konstruktor
Přispěvatel: Jaroslav Havlín 21. 12. 2020, 18:53:52
Ž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).

Kód: [Vybrat]
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
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 21. 12. 2020, 19:01:08
...

Díky za příspěvek.
Název: Re:Trait a konstruktor
Přispěvatel: listoper 21. 12. 2020, 19:03:53
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:
Kód: [Vybrat]
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".
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 21. 12. 2020, 19:37:54
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:
Kód: [Vybrat]
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í.
Název: Re:Trait a konstruktor
Přispěvatel: listoper 21. 12. 2020, 20:05:29
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:
Kód: [Vybrat]
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?
Název: Re:Trait a konstruktor
Přispěvatel: listoper 21. 12. 2020, 21:15:04
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...
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 21. 12. 2020, 21:31:24
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?
Název: Re:Trait a konstruktor
Přispěvatel: listoper 21. 12. 2020, 22:33:00
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.
Název: Re:Trait a konstruktor
Přispěvatel: Ondrej Nemecek 21. 12. 2020, 22:58:58
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.
Název: Re:Trait a konstruktor
Přispěvatel: registrovany_ava 22. 12. 2020, 09:53:45
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?
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 22. 12. 2020, 20:16:21
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.
Název: Re:Trait a konstruktor
Přispěvatel: Idris 22. 12. 2020, 21:42:53
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.
Název: Re:Trait a konstruktor
Přispěvatel: okalousek 23. 12. 2020, 01:25:30
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ázev: Re:Trait a konstruktor
Přispěvatel: Idris 23. 12. 2020, 11:04:15
něco na tom Golangu bude
Bude, hlavně od verze Go 2, která má dostat koncepty.
Název: Re:Trait a konstruktor
Přispěvatel: registrovany_ava 23. 12. 2020, 13:08:39
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ázev: Re:Trait a konstruktor
Přispěvatel: okalousek 23. 12. 2020, 16:08:59
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?
Kód: [Vybrat]
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ázev: Re:Trait a konstruktor
Přispěvatel: Idris 23. 12. 2020, 16:29:33
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 23. 12. 2020, 17:12:13
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 23. 12. 2020, 17:21:16
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.
Název: Re:Trait a konstruktor
Přispěvatel: Ink 23. 12. 2020, 19:30:53
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á?
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 24. 12. 2020, 00:15:18
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.
Název: Re:Trait a konstruktor
Přispěvatel: Idris 24. 12. 2020, 00:28:34
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?
Název: Re:Trait a konstruktor
Přispěvatel: Kit 24. 12. 2020, 00:56:14
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 24. 12. 2020, 01:09:04
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
Název: Re:Trait a konstruktor
Přispěvatel: Idris 24. 12. 2020, 01:56:28
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í.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 24. 12. 2020, 02:58:34
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.
Název: Re:Trait a konstruktor
Přispěvatel: Idris 24. 12. 2020, 04:51:31
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á.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 24. 12. 2020, 13:58:16
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.
Název: Re:Trait a konstruktor
Přispěvatel: Ink 24. 12. 2020, 14:21:55
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é.
Název: Re:Trait a konstruktor
Přispěvatel: okalousek 24. 12. 2020, 14:55:52
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é.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 25. 12. 2020, 23:29:33
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 25. 12. 2020, 23:31:52
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.)
Název: Re:Trait a konstruktor
Přispěvatel: okalousek 26. 12. 2020, 01:55:40
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.
Název: Re:Trait a konstruktor
Přispěvatel: BoneFlute 26. 12. 2020, 02:54:25
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...
Název: Re:Trait a konstruktor
Přispěvatel: Wrána diskuze 26. 12. 2020, 23:21:58
....................................

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