🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

10 total messages Started by Marek S Wed, 04 Sep 2019 20:11
TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408816
Author: Marek S
Date: Wed, 04 Sep 2019 20:11
58 lines
2541 bytes
Witam,

Biję się z myślami czy nie przesiąść się z JS ES6 na TypeScript. Właśnie 
testuję pod PHPStorm'em edycję i transkompilację TS i działa ten 
mechanizm wyśmienicie. Ucieszony tym zabrałem się za pierwszy skrypt i 
... poległem na podstawach. Stworzyłem dwie klasy jako moduły) Test i Test2:

abstract class Test {
     private _message: string;

     protected printMessage() {
         console.log(this._message);
     }

     protected constructor(message: string) {
         this._message = message;

     }
}

export default Test;

*****************************************

import Test from "./Test";

class Test2 extends Test{
     private _message: string;

     constructor(message:string) {
         super("dupa");
         this._message = message;
     }

     execute() {
         console.log(this._message);
         this.printMessage();
     }
}

let demo = new Test2("my message");
demo.execute();

Zadeklarowałem _message jako zmienną prywatną w obu klasach i... powstał 
konflikt! Transkompilator nie poradził sobie z tym. Oczekiwałbym 
samoczynnej zmiany nazwy funkcji by w wyjściowym JS nie było konfliktów. 
Zatem jak żyć? :-) To samo dotyczy metod. Te prywatne zwalczają się 
zamiast być niezależnymi w każdej z klas.

Póki co nie dostrzegam wielkich korzyści z przejścia na TS. Aby uzyskać 
wpełni prywatne zmienne, muszę ręcznie rzeźbić kod na symbolach - jak w 
natywnym JS. Jedynie IDE nieco ułatwi programowanie ukrywając to, co 
prywatne i czasem przypilnuje typów (ale tylko przy jawnych 
podstawieniach). Czy zatem warto bawić się w TS?

-- 
Pozdrawiam,
Marek
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408817
Author: Szyk Cech
Date: Thu, 05 Sep 2019 03:54
7 lines
1541 bytes
Na pewno wiesz co robisz?
_message raczej powinno być tylko jedno w obu klasach. Dziedziczenie 
polega na tym, że od przodka wjeżdża wszystko.
Inny problem jest taki, że _message jest prywatna. W C++ oznacza to, że 
nie jest ona dostępna dla potomków. W takiej sytuacji gdy ma być ona 
dostępna również dla potomka sugerowałbym dyrektywę protected jeśli coś 
takiego w ogóle jest w tym języku (protected stosuję w C++).
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408820
Author: Roman Tyczka
Date: Thu, 05 Sep 2019 07:50
51 lines
2629 bytes
On Wed, 4 Sep 2019 22:11:10 +0200, Marek S wrote:
> abstract class Test {
>      private _message: string;
> 
>      protected printMessage() {
>          console.log(this._message);
>      }
> 
>      protected constructor(message: string) {
>          this._message = message;
> 
>      }
> }
> 
> export default Test;
> 
> *****************************************
> 
> import Test from "./Test";
> 
> class Test2 extends Test{
>      private _message: string;
> 
>      constructor(message:string) {
>          super("dupa");
>          this._message = message;
>      }
> 
>      execute() {
>          console.log(this._message);
>          this.printMessage();
>      }
> }
> 
> let demo = new Test2("my message");
> demo.execute();
> 
> Zadeklarowałem _message jako zmienną prywatną w obu klasach i... powstał 
> konflikt! Transkompilator nie poradził sobie z tym. Oczekiwałbym 
> samoczynnej zmiany nazwy funkcji by w wyjściowym JS nie było konfliktów. 
> Zatem jak żyć? :-) To samo dotyczy metod. Te prywatne zwalczają się 
> zamiast być niezależnymi w każdej z klas.

Nie żabym się znał na TS, choć mam w planie nim się zająć, ale tak na
logikę to zastanawia mnie które _message wg Ciebie miałaby wziąć metoda
printMessage() wywołana z klasy Test2? Dla mnie to ewidentny konflikt. 


-- 
pozdrawiam
Roman Tyczka
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408821
Author: Marek S
Date: Thu, 05 Sep 2019 17:43
23 lines
1886 bytes
W dniu 2019-09-05 o 09:50, Roman Tyczka pisze:
> 
> Nie żabym się znał na TS, choć mam w planie nim się zająć, ale tak na
> logikę to zastanawia mnie które _message wg Ciebie miałaby wziąć metoda
> printMessage() wywołana z klasy Test2? Dla mnie to ewidentny konflikt.
> 

Kurcze, jesteś drugą osobą, która o to dziś mnie pyta. Dla mnie sprawa 
jest tak oczywista jak oddychanie. Napisz sobie skrypt w PHP o podobnej 
strukturze i tam dostaniesz odpowiedź. Jeśli nie PHP, to może C#. Jeśli 
miałbym tworzyć standardy, to z pewnością powieliłbym zachowanie się 
prywatnych zmiennych z tego typu języków.

Reasumując, metoda printMessage() powinno zwrócić wartość "dupa". 
Istnienie identycznej zmiennej prywatnej w klasie potomnej nie ma prawa 
nadpisywać tego, co jest w bazowej.

Przedstaw mi swój tok rozumowania, który powoduje, że masz wątpliwości. 
Ciekawi mnie ich źródło.

-- 
Pozdrawiam,
Marek
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408818
Author: Marek S
Date: Thu, 05 Sep 2019 17:58
78 lines
2576 bytes
W dniu 2019-09-05 o 05:54, Szyk Cech pisze:

> Na pewno wiesz co robisz?

Wydaje mi się, że tak. Od lat programuję w natywnym JS.

> _message raczej powinno być tylko jedno w obu klasach. Dziedziczenie 
> polega na tym, że od przodka wjeżdża wszystko.
> Inny problem jest taki, że _message jest prywatna. 

No i o tym problemie mowa. W natywnym JS ES6 nie mam problemu z 
tworzeniem zmiennych prywatnych, a i metod też - choć ponoć takowe nie 
istnieją. TS już tego nie potrafi więc w tym zakresie kuleje. Oto przykład:

Moduł 1:

let privateMethod = Symbol();
let privateVar = Symbol();

class a {
   constructor() {
     this[privateVar]=5;
   }

   this[privateMethod]() {
     console.log(this[privateVar]);
   }

   printA() {
     this[privateMethod]();
   }

}

Moduł 2:

import a from ...

let privateMethod = Symbol();
let privateVar = Symbol();

class b extends a {
   constructor() {
     this[privateVar]=10;
   }

   printB() {
     this.printA();
     console.log(this[privateVar]);
   }

}

let obj = new b();
obj.printB(); // metoda publiczna

// 5
// 10

obj.printA(); //metoda publiczna

//5

obj[privateMethod](); //metoda prywatna

//error

W powyższym przykładzie privateVar jest prawdziwie prywatne dla obu 
klas. Wywołanie prywatnej metody privateMethod kończy się błędem. Da się 
to zrobić w ES6? Da się! A TypeScript wymięka. A wystarczyłoby aby 
transkodował prywatne zmienne i metody do konstrukcji z wykorzystaniem 
symboli.

Kod pisałem z palca - więc mogłem jakieś błędy popełnić.

-- 
Pozdrawiam,
Marek
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408819
Author: Marek S
Date: Thu, 05 Sep 2019 18:21
17 lines
1257 bytes
Korekta. Już zauważyłem błąd. Zamiast:

>    this[privateMethod]() {
>      console.log(this[privateVar]);
>    }

Miało być:

[privateMethod]() {
      console.log(this[privateVar]);
    }

Jeśli jeszcze jakiś błąd będzie, to z góry przepraszam.

-- 
Pozdrawiam,
Marek
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408822
Author: Tomek
Date: Fri, 06 Sep 2019 11:55
12 lines
1564 bytes
W dniu 05.09.2019 o 19:43, Marek S pisze:
> W dniu 2019-09-05 o 09:50, Roman Tyczka pisze:
>>
>> Nie żabym się znał na TS
> 
> Przedstaw mi swój tok rozumowania, który powoduje, że masz wątpliwości. 
> Ciekawi mnie ich źródło.
> 

Też pojęcia nie mam o TS ale w JS jeśli wewnątrz funkcji jest 
wykorzystywane "this" to te "this" może znaczyć coś kompletnie innego w 
zależności od kontekstu jak jest wywoływana ta funkcja.
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408823
Author: Marek S
Date: Fri, 06 Sep 2019 12:57
28 lines
2342 bytes
W dniu 2019-09-06 o 13:55, Tomek pisze:

> Też pojęcia nie mam o TS ale w JS jeśli wewnątrz funkcji jest 
> wykorzystywane "this" to te "this" może znaczyć coś kompletnie innego w 
> zależności od kontekstu jak jest wywoływana ta funkcja.
> 

Ok, ale ja nie o tym. Po pierwsze ustalmy, że nie chodzi o funkcje ale o 
klasy (słowo kluczowe class). Słowo kluczowe this w każdej metodzie 
klasy znaczy dokładnie to samo i ma zasięg całej klasy.

A tematem rozmowy jest to, że w natywnym JS da się, choć nie pięknie, 
zdefiniować prywatne metody i właściwości. Natomiast w TS, prywatne 
zmienne są wpół prywatne. Transkompilator, podczas zamiany TS w JS, nie 
radzi sobie z przekształceniem prywatnych elementów do postaci JS, w 
taki sposób, by prywatność zachować. Zamiast tego wyświetla error 
mówiący o tym, że zmienna prywatna w klasie potomnej pokrywa się ze 
zmienną prywatną w klasie bazowej - co spowoduje konflikt. I faktycznie 
wynikowy kod JS nie będzie działał w takim przypadku.

Konkluzja jest taka, że TS jest przydatny, ale wobec takiej niedoróby, 
póki co trzymam się natywnego JS. Jakoś mi się to wydaje 
nieprawdopodobne aby twórcy TS to przeoczyli. Dlatego podpytuję tutaj o 
to czy jest jakieś obejście problemu.

-- 
Pozdrawiam,
Marek
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408824
Author: Roman Tyczka
Date: Sat, 07 Sep 2019 14:12
46 lines
3276 bytes
On Thu, 5 Sep 2019 19:43:52 +0200, Marek S wrote:

>> Nie żabym się znał na TS, choć mam w planie nim się zająć, ale tak na
>> logikę to zastanawia mnie które _message wg Ciebie miałaby wziąć metoda
>> printMessage() wywołana z klasy Test2? Dla mnie to ewidentny konflikt.
>> 
> 
> Kurcze, jesteś drugą osobą, która o to dziś mnie pyta. Dla mnie sprawa 
> jest tak oczywista jak oddychanie. Napisz sobie skrypt w PHP o podobnej 
> strukturze i tam dostaniesz odpowiedź. 

Ja nie napisałem, że nie znam odpowiedzi w innych językach, napisałem, że
dla mnie to nie jest oczywiste jak Ci się wydaje.

> Jeśli nie PHP, to może C#. Jeśli 
> miałbym tworzyć standardy, to z pewnością powieliłbym zachowanie się 
> prywatnych zmiennych z tego typu języków.

To, że w jakichś językach jest to tak czy inaczej nie jest dowodem, że tak
powinno być.
 
> Reasumując, metoda printMessage() powinno zwrócić wartość "dupa". 
> Istnienie identycznej zmiennej prywatnej w klasie potomnej nie ma prawa 
> nadpisywać tego, co jest w bazowej.
> 
> Przedstaw mi swój tok rozumowania, który powoduje, że masz wątpliwości. 
> Ciekawi mnie ich źródło.

Źródłem są przemyślenia. Oto mój tok rozumowania:
Tworzysz obiekt klasy Test2. Klasa Test2 ma prywatne pole ukryte pod
this._message. Wołasz z tego obiektu metodę, która zwraca this._message.
Skoro jest to obiekt klasy Test2 to dla tego typu this._message jest czymś
innym niż dla typy Test, prawda? Dla mnie to sprawa oczywista jak
oddychanie ;-) Jest tu wyraźna niejednoznaczność i punkt sporny, który
warto wywalić na twarz chociażby ostrzeżeniem.

To, że Java czy C# zwraca bezrefleksyjnie (czy są jakieś ostrzeżenia
kompilatora?) wcale nie jest fajne, bo łatwo o masę głupich błędów, które
transpiler TS wyłapuje jak zeznałeś. Mnie to bardzo cieszy, bo nie uważam,
że taka praktyka jak identyczna nazwa prywatnego pola w dziedziczeniu to
dobra praktyka. Ot wszystko.


-- 
pozdrawiam
Roman Tyczka
Re: TypeScript - jak uzyskać zmienne prywatne? Gdzie korzyści z TS?
#408825
Author: Marek S
Date: Sat, 07 Sep 2019 22:07
80 lines
4847 bytes
W dniu 2019-09-07 o 16:12, Roman Tyczka pisze:

> 
>> Jeśli nie PHP, to może C#. Jeśli miałbym tworzyć standardy, to z
>> pewnością powieliłbym zachowanie się prywatnych zmiennych z tego
>> typu języków.
> 
> To, że w jakichś językach jest to tak czy inaczej nie jest dowodem,
> że tak powinno być.

Chwila, ale nie rozmawiamy tu o postępowaniu sądowym, czy rozkminianiu
zagadek matematycznych by o jakichś dowodach wspominać.

Jeśli chcesz bawić się w dowody zachowania się zmiennych prywatnych w
JS, to z natury rzeczy stoisz na przegranej pozycji, bo czegoś takiego w
JS nie ma ... przynajmniej do momentu gdy zastosujemy sztuczek, jakie
opisałem. Wtedy można je wykrzesać nawet w natywnym JS i zachowują się
one dokładnie tak samo jak w innych językach.

Jeśli natomiast mówimy o zachowaniu się zmiennych prywatnych w TS to
może warto wrócić do podstaw i przeczytać definicję zmiennej prywatne.
Jej definicja jest jedna i wspólna dla wszystkich języków:

https://pl.wikipedia.org/wiki/Zmienna_prywatna

lub tu:

https://pl.wikipedia.org/wiki/Zmienna_(informatyka)

"Zmienne zadeklarowane w module mogą być zmiennymi prywatnymi modułu –
dostępnymi wyłącznie z jego wnętrza – lub zmiennymi publicznymi
(eksportowanymi) – dostępnymi tam, gdzie moduł jest wykorzystywany.
Podobnie jest ze zmiennymi w klasie – mogą być dostępne:
tylko dla danej klasy (zmienna prywatna),"

https://www.p-programowanie.pl/cpp/klasy-c/

"private – dostęp do składników klasy jest zabroniony z poza ciała klasy"

Nie chcę już cytować linków na ten sam temat w kontekście PHP czy Java. 
Sposób zachowania zmiennych prywatnych jest tam również zgodny z definicją.

TS łamie tą definicję. Zdefiniowana przez niego zmienna prywatna w
klasie, w kodzie wynikowym będzie podlegać nadpisywaniu przez klasę
potomną. Owszem, powstanie podczas transkompilacji absurdalny błąd,
który nie ma prawa zaistnieć, a wadliwy  kod wynikowy i tak wygeneruje się.

> Źródłem są przemyślenia. Oto mój tok rozumowania: Tworzysz obiekt
> klasy Test2. Klasa Test2 ma prywatne pole ukryte pod this._message.
> Wołasz z tego obiektu metodę, która zwraca this._message. Skoro jest
> to obiekt klasy Test2 to dla tego typu this._message jest czymś innym
> niż dla typy Test, prawda? Dla mnie to sprawa oczywista jak 
> oddychanie ;-) Jest tu wyraźna niejednoznaczność i punkt sporny,
> który warto wywalić na twarz chociażby ostrzeżeniem.
> 
> To, że Java czy C# zwraca bezrefleksyjnie (czy są jakieś ostrzeżenia 
> kompilatora?) wcale nie jest fajne, bo łatwo o masę głupich błędów,
> które transpiler TS wyłapuje jak zeznałeś. Mnie to bardzo cieszy, bo
> nie uważam, że taka praktyka jak identyczna nazwa prywatnego pola w
> dziedziczeniu to dobra praktyka. Ot wszystko.
> 

Hmmm... wydaje mi się, że taki sposób rozumowania i obawy o to, co jak
mają się zachowywać zmienne prywatne (niezależnie od języka 
programowania) wynikają z Twojego niezrozumienia czym w ogóle są zmienne 
prywatne. Zapewniam Cię, że ani w C ani w PHP obecność zmiennej 
prywatnej w klasie bazowej nie będzie podlegać nadpisaniu w klasie 
potomnej bo to są dwa oddzielne byty w dwóch różnych obszarach RAM. 
Żadne ostrzeżenia o używaniu zmiennych prywatnych w obu klasach nie 
powstaną w trakcie kompilacji C lub używania PHP bo ... nie ma o czym 
ostrzegać. Nie ma w tym żadnego błędu jak i obie zmienne nie będą w 
konflikcie. Jedynie TS się wyłamuje i nadużywa terminu prywatności. 
Przypuszczam, że jest to zwyczajny błąd twórców TS.

Spytam jeszcze: czy Ty w ogóle programujesz z użyciem OOP? Masz 
wątpliwości co do najbardziej podstawowych pojęć w tej technice.

-- 
Pozdrawiam,
Marek
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads