Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: vyvojar 20. 12. 2017, 18:21:42

Název: Swift a protected access control
Přispěvatel: vyvojar 20. 12. 2017, 18:21:42
Co si myslíte o tom, že Swift od Applu nemá protected a tedy nelze mít property/metody, které by šlo použít pouze v rámci hierarchie dědičnosti a ne zvenčí?

Četl jsem jeden článek, kde důvod byl asi takový, že v podstatě protected je k ničemu a žádnou ochranu přístupu neposkytuje, protože nikomu nebrání třídu podědit a prvek zveřejnit jako public.
Jenže teď dám příklad, např. třída Thread mívá často nějakou protected metodu run, která je určena pro překrytí a je volána, když se vlákno nastartuje. Ve Swiftu by nic nebránilo tu metodu run zavolat napřímo, což je v podstatě programátorská chyba.

No co si o tom myslíte? Je to ok a prostě brát to tak, že kdo např. v tom výše uveden případě zavolá napřímo tu metodu run, tak je to jeho problém, že to někde failne? Já nevím, nějak se nemůžu rozhodnout, jestli je to správný přístup nebo ne a psát ten kód tak, že i já třeba dřív nebo později udělám fail ve vlastním kódu, že si něčeho nevšimnu a použiju člen, který zvenčí nemám používat a pak budu 2 dny debuggovat nebo mám hledat neustále nějaký berličky, jak to ošetřit tak, aby došlo k nějakýmu fatalerroru, když public člen bude použit z venčí i když jeho sémantika je protected?:D
Název: Re:Swift a protected access control.
Přispěvatel: gll 20. 12. 2017, 19:06:03
tu třídu Thread bych rád viděl.
Název: Re:Swift a protected access control.
Přispěvatel: BoneFlute 20. 12. 2017, 19:50:34
Ano, souhlasím s tím, že protected je k ničemu. (Dokonce ho už nějaký ten pátek v žádném mém kódu nepoužívám.)

Polož si otázku: proč by měl někdo bránit tomu, aby se zavolala metoda run napřímo? Proč není ta třída navržena tak, aby napřímo volat šla?
Název: Re:Swift a protected access control.
Přispěvatel: vyvojar 20. 12. 2017, 20:34:42
Ano, souhlasím s tím, že protected je k ničemu. (Dokonce ho už nějaký ten pátek v žádném mém kódu nepoužívám.)

Polož si otázku: proč by měl někdo bránit tomu, aby se zavolala metoda run napřímo? Proč není ta třída navržena tak, aby napřímo volat šla?

Protože konkrétně ten Thread se pouští přes metodu start, ta je veřejná a metoda run má sloužit pro implementaci toho, co má to vlákno provádět. Někdo by si to mohl třeba spléct a zavolat run v domnění, že to pouští to vlákno. Kdyby byla protected, tak by se to nestalo. Mně se to prostě nelíbí.

No jako teoreticky by to mohlo jít tak, že bych úplně upustit od toho klasickýho konceptu, co je vidět skoro všude, ale udělat to spíš tak, že by se vlákno vůbec nedědilo za účelem implementace logiky, co má vykonávat (překrytí nějaká PROTECTED metody), ale že by se tomu vláknu předal nějaký IRunnable nebo něco, který by měl jednu metodu run a ta by se tím vláknem pustila. To by pak bylo zase trochu odklonění spíš směrem k nějaké kompozici. No budu si to muset promyslet a podívat se na nějaký moderný způsoby vývoje v těch nových jazycích. 
Název: Re:Swift a protected access control.
Přispěvatel: vyvojar 20. 12. 2017, 20:38:12
tu třídu Thread bych rád viděl.

Je to ten klasický koncept, kdy máš třídu Thread a ta má nějakou metodu run, která se pak volá, když nastartuješ vlákno.
Prostě třeba v tom Swiftu

Kód: [Vybrat]
public class MyThread: Thread
{
  public func run()
  {
     print("Hello from thread!")
  }
}

let thread = MyThread()
thread.start() // toto spusti vlakno a v novem vlakne se provede run()
//thread.run() // TOTO je spatne, to pusti run v aktualnim vlakne, bohuzel nemame protected, takze se tomu neda zabranit
Název: Re:Swift a protected access control.
Přispěvatel: vyvojar 20. 12. 2017, 20:39:13
tu třídu Thread bych rád viděl.

Je to ten klasický koncept, kdy máš třídu Thread a ta má nějakou metodu run, která se pak volá, když nastartuješ vlákno.
Prostě třeba v tom Swiftu

Kód: [Vybrat]
public class MyThread: Thread
{
  public func run()
  {
     print("Hello from thread!")
  }
}

let thread = MyThread()
thread.start() // toto spusti vlakno a v novem vlakne se provede run()
//thread.run() // TOTO je spatne, to pusti run v aktualnim vlakne, bohuzel nemame protected, takze se tomu neda zabranit

zapomnel jsem override pro vsimavejsi :)
Název: Re:Swift a protected access control.
Přispěvatel: gll 20. 12. 2017, 20:53:52
tu třídu Thread bych rád viděl.

Je to ten klasický koncept, kdy máš třídu Thread a ta má nějakou metodu run, která se pak volá, když nastartuješ vlákno.
Prostě třeba v tom Swiftu

Kód: [Vybrat]
public class MyThread: Thread
{
  public func run()
  {
     print("Hello from thread!")
  }
}

let thread = MyThread()
thread.start() // toto spusti vlakno a v novem vlakne se provede run()
//thread.run() // TOTO je spatne, to pusti run v aktualnim vlakne, bohuzel nemame protected, takze se tomu neda zabranit

myslel jsem nějakou knihovnu, kde je ta metoda protected.
Název: Re:Swift a protected access control.
Přispěvatel: vyvojar 20. 12. 2017, 20:56:47
tu třídu Thread bych rád viděl.

Je to ten klasický koncept, kdy máš třídu Thread a ta má nějakou metodu run, která se pak volá, když nastartuješ vlákno.
Prostě třeba v tom Swiftu

Kód: [Vybrat]
public class MyThread: Thread
{
  public func run()
  {
     print("Hello from thread!")
  }
}

let thread = MyThread()
thread.start() // toto spusti vlakno a v novem vlakne se provede run()
//thread.run() // TOTO je spatne, to pusti run v aktualnim vlakne, bohuzel nemame protected, takze se tomu neda zabranit

myslel jsem nějakou knihovnu, kde je ta metoda protected.

Treba http://doc.qt.io/qt-5/qthread.html
Název: Re:Swift a protected access control.
Přispěvatel: BoneFlute 21. 12. 2017, 00:29:00
Ano, souhlasím s tím, že protected je k ničemu. (Dokonce ho už nějaký ten pátek v žádném mém kódu nepoužívám.)

Polož si otázku: proč by měl někdo bránit tomu, aby se zavolala metoda run napřímo? Proč není ta třída navržena tak, aby napřímo volat šla?

Protože konkrétně ten Thread se pouští přes metodu start, ta je veřejná a metoda run má sloužit pro implementaci toho, co má to vlákno provádět. Někdo by si to mohl třeba spléct a zavolat run v domnění, že to pouští to vlákno. Kdyby byla protected, tak by se to nestalo. Mně se to prostě nelíbí.

No jasně. To známe. Ale já se ptám proč by to tak mělo být řešené? Není to poněkud zbytečně složité? Proč to prostě není v té metodě start?

No jako teoreticky by to mohlo jít tak, že bych úplně upustit od toho klasickýho konceptu, co je vidět skoro všude, ale udělat to spíš tak, že by se vlákno vůbec nedědilo za účelem implementace logiky, co má vykonávat (překrytí nějaká PROTECTED metody), ...
To, že je to vidět skoro všude neznamená, že to je dobře. Já bych klidně tvrdil, že je to prostě špatně :-)
Název: Re:Swift a protected access control
Přispěvatel: Vykook 21. 12. 2017, 09:40:53
Osobně preferuji jízdu na kole bez pomocných koleček, ale proti gustu...
Název: Re:Swift a protected access control.
Přispěvatel: vyvojar 21. 12. 2017, 10:14:00
Ano, souhlasím s tím, že protected je k ničemu. (Dokonce ho už nějaký ten pátek v žádném mém kódu nepoužívám.)

Polož si otázku: proč by měl někdo bránit tomu, aby se zavolala metoda run napřímo? Proč není ta třída navržena tak, aby napřímo volat šla?

Protože konkrétně ten Thread se pouští přes metodu start, ta je veřejná a metoda run má sloužit pro implementaci toho, co má to vlákno provádět. Někdo by si to mohl třeba spléct a zavolat run v domnění, že to pouští to vlákno. Kdyby byla protected, tak by se to nestalo. Mně se to prostě nelíbí.

No jasně. To známe. Ale já se ptám proč by to tak mělo být řešené? Není to poněkud zbytečně složité? Proč to prostě není v té metodě start?

No jako teoreticky by to mohlo jít tak, že bych úplně upustit od toho klasickýho konceptu, co je vidět skoro všude, ale udělat to spíš tak, že by se vlákno vůbec nedědilo za účelem implementace logiky, co má vykonávat (překrytí nějaká PROTECTED metody), ...
To, že je to vidět skoro všude neznamená, že to je dobře. Já bych klidně tvrdil, že je to prostě špatně :-)
Jak by si to chtel udelat? Ty musis nativnimu vlaknu nejak rict, co se ma zavolat v tom novem vlakne - ocekava pointer na funkci, ktera prijima jeden void parametr a tu funkci pak zavola s parametrem, ktery ty predas. Takze treba na posixu volam nejakou nativni funkci pthread_create a jako tu startup rutinu predavam statickou metodu Thread._start a parametr tu instanci Thread. Ve _start pak pretypuju void* na Thread a zavolam _startImpl, ten provede nejaky setup a zavola run:).
Název: Re:Swift a protected access control.
Přispěvatel: podhy 21. 12. 2017, 11:03:48
Ano, souhlasím s tím, že protected je k ničemu. (Dokonce ho už nějaký ten pátek v žádném mém kódu nepoužívám.)

Polož si otázku: proč by měl někdo bránit tomu, aby se zavolala metoda run napřímo? Proč není ta třída navržena tak, aby napřímo volat šla?

Protože konkrétně ten Thread se pouští přes metodu start, ta je veřejná a metoda run má sloužit pro implementaci toho, co má to vlákno provádět. Někdo by si to mohl třeba spléct a zavolat run v domnění, že to pouští to vlákno. Kdyby byla protected, tak by se to nestalo. Mně se to prostě nelíbí.

No jasně. To známe. Ale já se ptám proč by to tak mělo být řešené? Není to poněkud zbytečně složité? Proč to prostě není v té metodě start?

No jako teoreticky by to mohlo jít tak, že bych úplně upustit od toho klasickýho konceptu, co je vidět skoro všude, ale udělat to spíš tak, že by se vlákno vůbec nedědilo za účelem implementace logiky, co má vykonávat (překrytí nějaká PROTECTED metody), ...
To, že je to vidět skoro všude neznamená, že to je dobře. Já bych klidně tvrdil, že je to prostě špatně :-)
Jak by si to chtel udelat? Ty musis nativnimu vlaknu nejak rict, co se ma zavolat v tom novem vlakne - ocekava pointer na funkci, ktera prijima jeden void parametr a tu funkci pak zavola s parametrem, ktery ty predas. Takze treba na posixu volam nejakou nativni funkci pthread_create a jako tu startup rutinu predavam statickou metodu Thread._start a parametr tu instanci Thread. Ve _start pak pretypuju void* na Thread a zavolam _startImpl, ten provede nejaky setup a zavola run:).

budu předávat funkci start anonymní funkci, která se bude v tom vláknu / vlákench vykonávat?
Název: Re:Swift a protected access control.
Přispěvatel: gll 21. 12. 2017, 11:18:52
budu předávat funkci start anonymní funkci, která se bude v tom vláknu / vlákench vykonávat?

nemusí být anonymní. Dědění je v tomto případě úplně zbytečné.
Název: Re:Swift a protected access control.
Přispěvatel: podhy 21. 12. 2017, 11:44:17
budu předávat funkci start anonymní funkci, která se bude v tom vláknu / vlákench vykonávat?

nemusí být anonymní. Dědění je v tomto případě úplně zbytečné.

jo jasný...tady už je to i v závislosti na jazyku, kterej použiju, ale dědičnost mi tady taky rozhdoně nepřijde nutná spíš zbytečná
Název: Re:Swift a protected access control.
Přispěvatel: . 22. 12. 2017, 07:53:34
budu předávat funkci start anonymní funkci, která se bude v tom vláknu / vlákench vykonávat?

nemusí být anonymní. Dědění je v tomto případě úplně zbytečné.

jo jasný...tady už je to i v závislosti na jazyku, kterej použiju, ale dědičnost mi tady taky rozhdoně nepřijde nutná spíš zbytečná
Dědičnost je zbytečná skoro vždy.
Název: Re:Swift a protected access control
Přispěvatel: SB 22. 12. 2017, 10:29:36
Co si myslíte o tom, že Swift od Applu nemá protected a tedy nelze mít property/metody, které by šlo použít pouze v rámci hierarchie dědičnosti a ne zvenčí?

Že jste přišel o klíčový prvek OOP - zapouzdření. Tím se závažně mění koncepce výpočtu (i když ne každý je schopen to pochopit, což se ukáže v diskusi).

Četl jsem jeden článek, kde důvod byl asi takový, že v podstatě protected je k ničemu a žádnou ochranu přístupu neposkytuje, protože nikomu nebrání třídu podědit a prvek zveřejnit jako public.

A který pičus ho napsal? Jak se dostanete do instance třídy A k její neveřejné vlastnosti BŽ pomocí zděděné třídy B implementující veřejný přístup k BŽ? Těžko budete v instanci A používat metodu z B.

Jenže teď dám příklad, např. třída Thread mívá často nějakou protected metodu run, která je určena pro překrytí a je volána, když se vlákno nastartuje. Ve Swiftu by nic nebránilo tu metodu run zavolat napřímo, což je v podstatě programátorská chyba...

Ona metoda run je nevěřejná z nějakého důvodu, a to toho, že objekt je výhradním řešitelem problému. V okamžiku, kdy máte pseudozapouzdření (Python) nebo žádné zapouzdření a run zavoláte, tak jste to posral, protože se s tím nepočítalo. A posrat to jde.
Název: Re:Swift a protected access control.
Přispěvatel: SB 22. 12. 2017, 10:41:13
No jasně. To známe. Ale já se ptám proč by to tak mělo být řešené? Není to poněkud zbytečně složité? Proč to prostě není v té metodě start?

Vy víte, co se děje mezi začátkem start a spuštěním run?
Název: Re:Swift a protected access control.
Přispěvatel: SB 22. 12. 2017, 10:43:12
budu předávat funkci start anonymní funkci, která se bude v tom vláknu / vlákench vykonávat?

To samozřejmě jde, používá se to např. v Pythonu nebo Smalltalku.
Název: Re:Swift a protected access control.
Přispěvatel: SB 22. 12. 2017, 10:45:01
Dědičnost je zbytečná skoro vždy.

Rozlišujte názor od prokazatelné skutečnosti.
Název: Re:Swift a protected access control.
Přispěvatel: ooooop 22. 12. 2017, 10:49:46
Dědičnost je zbytečná skoro vždy.

Rozlišujte názor od prokazatelné skutečnosti.

+1
Název: Re:Swift a protected access control.
Přispěvatel: gll 22. 12. 2017, 10:53:08
budu předávat funkci start anonymní funkci, která se bude v tom vláknu / vlákench vykonávat?

To samozřejmě jde, používá se to např. v Pythonu nebo Smalltalku.

používá se to téměř všude i v c/c++. V boost::thread předáváte funkci konstruktoru.
Název: Re:Swift a protected access control.
Přispěvatel: gll 22. 12. 2017, 11:03:03
Dědičnost je zbytečná skoro vždy.

Rozlišujte názor od prokazatelné skutečnosti.

prokazatelná skutečnost je, že použití dědičnosti v tomto případě prodlouží kód.
Název: Re:Swift a protected access control.
Přispěvatel: BoneFlute 23. 12. 2017, 00:06:32
No jasně. To známe. Ale já se ptám proč by to tak mělo být řešené? Není to poněkud zbytečně složité? Proč to prostě není v té metodě start?

Vy víte, co se děje mezi začátkem start a spuštěním run?
Měl bych to řešit? Měl bych to vědět?
Název: Re:Swift a protected access control
Přispěvatel: Sten 23. 12. 2017, 11:45:37
Mě ta argumentace přijde nesmyslná. Protected je contract. Je vhodné, když kompilátor při přímém přístupu k protected proměnné zařve, že tohle asi není to, co programátor chtěl udělat, ale programátor by měl mít možnost to obejít, pokud se domnívá, že to potřebuje obejít. Proto zrušit protected se zdůvodněním, že programátor ho může obejít, je nesmysl; to není chyba zapouzdření, to je vlastnost toho, že programy tvoří programátor.

U čeho mi naopak uniká rozumný důvod, proč existuje, je private. Poděděná třída má mít možnost přistupovat k vnitřnímu stavu děděné třídy, jinak je dědění velmi omezené (v používaných analogiích private ani nedává smysl, pokud Plachetnice dědí Loď, tak má přeci přístup ke všem vlastnostem Lodi). Vím o případech, kdy jsou nějaké vnitřní stavy, kde přístup poděděné třídy nedává smysl, ale ještě jsem neviděl případ, kdy by to nebylo způsobené tím, že si programátor usnadnil práci a nedostatečně dekomponoval ten objekt (třeba u té Lodi tím, že nějaké fyzikální vlastnosti nechal počítat přímo Loď, ale Loď přeci fyziku nedefinuje). Ještě nikdy jsem neviděl případ, kdy by private byl opravdu potřeba, naopak jsem viděl mnoho případů, kdy neuvěřitelně házel klacky pod nohy (C++ STL je velmi dobrý příklad).
Název: Re:Swift a protected access control
Přispěvatel: BoneFlute 23. 12. 2017, 19:04:03
... Protected je contract. ...

U čeho mi naopak uniká rozumný důvod, proč existuje, je private. Poděděná třída má mít možnost přistupovat k vnitřnímu stavu děděné třídy, jinak je dědění velmi omezené ...

Pointa protected a private je v tom, že private je interní problém daného objektu. Ten si pomocí něho řeší své problémy, které ale nechce zveřejňovat z dobrého důvodu: jakmile to zveřejní, stane se to součástí api, a už to nesmí změnit. Jinak rozbije uživatele. A čím šiřší api, tím více kombinací musí programátor ošéfovat. Když je to private, tak to může kdykoliv přepsat. To je děsně osvobozující.

U protected v praxi vidím zlozvyk programátorů, kteří místo toho, aby metodě dali private, tak jí dají raději protected, protože co kdyby to někdy chtěli přetížit že jo. Když by dávali protected namísto public, tak mlčím.
Název: Re:Swift a protected access control
Přispěvatel: vyvojar 23. 12. 2017, 20:33:15
Jo tak jsem to nakonec udělal, že vlákno má property typu Runnable, což je protocol s jednou metodu run.  Property je jen getter a je to na programátorovi, aby si třídu podědil a ten getter překryl a vracel to, co je specifické pro jeho thread. Dobrý to je v tom, že se nestane, že by mu tam někdo přes setter nastavil instanci, kterou nepředpokládá. A nějaký ty featury jako vytvoření instance vlákna z closuru apod.. to se dá udělat přes extension, případně to tam můžu klidně přidat jako statickou metodu. No prostě teď mi to přijde jako nej řešení.

Ta absence protected je ale dost napytel no. V apple kódech jsou snad komenty typu, že toto nemá být používáno jako public, i když to public je, protože tam prostě není protected :)
Název: Re:Swift a protected access control
Přispěvatel: gll 23. 12. 2017, 20:54:57
Jo tak jsem to nakonec udělal, že vlákno má property typu Runnable, což je protocol s jednou metodu run.  Property je jen getter a je to na programátorovi, aby si třídu podědil a ten getter překryl a vracel to, co je specifické pro jeho thread. Dobrý to je v tom, že se nestane, že by mu tam někdo přes setter nastavil instanci, kterou nepředpokládá. A nějaký ty featury jako vytvoření instance vlákna z closuru apod.. to se dá udělat přes extension, případně to tam můžu klidně přidat jako statickou metodu. No prostě teď mi to přijde jako nej řešení.

Ta absence protected je ale dost napytel no. V apple kódech jsou snad komenty typu, že toto nemá být používáno jako public, i když to public je, protože tam prostě není protected :)

proč vůbec něco takového děláš a nepoužiješ standardní knihovnu?
Název: Re:Swift a protected access control
Přispěvatel: vyvojar 23. 12. 2017, 21:26:24
Jo tak jsem to nakonec udělal, že vlákno má property typu Runnable, což je protocol s jednou metodu run.  Property je jen getter a je to na programátorovi, aby si třídu podědil a ten getter překryl a vracel to, co je specifické pro jeho thread. Dobrý to je v tom, že se nestane, že by mu tam někdo přes setter nastavil instanci, kterou nepředpokládá. A nějaký ty featury jako vytvoření instance vlákna z closuru apod.. to se dá udělat přes extension, případně to tam můžu klidně přidat jako statickou metodu. No prostě teď mi to přijde jako nej řešení.

Ta absence protected je ale dost napytel no. V apple kódech jsou snad komenty typu, že toto nemá být používáno jako public, i když to public je, protože tam prostě není protected :)

proč vůbec něco takového děláš a nepoužiješ standardní knihovnu?

Já standardní knihovnu používám, ale opravdu jen tu standardní knihovnu. Ne ten Foundation (https://github.com/apple/swift-corelibs-foundation), kde jsou věcí jako mutexy, vlákna, to si implementuju sám, protože mi to z toho Foundation nevyhovuje.
Např. v té vlastní implementaci wrapperu nad nativním vláknem to mám udělané tak, že je tam nějaká metoda finish, která se volá pro každé vlákno VŽDYCKY než doběhne, i když ho někdo zruší třeba přes pthread_cancel. Takže to moje vlákno má pěkně jasnej a kontrolovanej životní cyklus.To bych s tím vláknem z Foundation nedokázal, protože je strašně simple wrapper nedomyšlenej.