🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.php
14 messages
14 total messages Started by Marek S Thu, 25 Jan 2018 19:19
Nikomu niepotrzebne zmienne prywatne?
#231922
Author: Marek S
Date: Thu, 25 Jan 2018 19:19
61 lines
2698 bytes
Witam.

Mój wątek dotyczy JS ale można go uogólnić. Otóż kiedyś programowałem 
aplikacje w C++ i nie tylko w tym języku. Zmienne prywatne występowały w 
kodach jak tlen w powietrzu. Sporo obecnie programuję w PHP i JS. Przy 
okazji edycji ECMA6 tego ostatniego języka zdumiały mnie dwie rzeczy:

1. Wprowadzono wreszcie pojęcie klas i dziedziczenia ale... zignorowano 
zmienne prywatne. Nie ma czegoś takiego w samych założeniach.

2. Gdy na międzynarodowym forum zapytałem o potrzebę symulacji zmiennych 
prywatnych, wywołałem konsternację. Uzyskiwałem odpowiedzi w stylu 
przecież tak ma być, co tu kombinować! Argumentacja moja w postaci 
takiej iż jeśli wszystkie zmienne będą publiczne w dziedziczonych 
klasach i nadpiszą się niechcący (bo autor klasy B może nie wiedzieć 
jakich nazw nie powinien używać aby nie nadpisać przypadkiem tych z 
klasy bazowej A - gdy obie są rozwijane więc nowe zmienne będą się 
pojawiać), uzyskałem odpowiedź iż: no jak to możliwe, przecież w 
dokumentacji poszczególnych klas trzeba pisać jakich nazw nie używać.


Zilustruję problem za pomocą JS:

"use strict";

class aClass {
     readFromA() {
         console.log(this.a);
     }


     constructor() {
         this.a = 5;
     }
}

class bClass extends aClass {
     readFromB() {
         console.log(this.a);
     }


     constructor() {
         super();
         this.a=10;
     }
}

let bc=new bClass();
bc.readFromA(); //pokaże 10
bc.readFromB(); //pokaże 10

Wynik nie zaskakuje a ja głupi uparłem się by obie klasy mogły mieć 
swoją prywatną zmienną "a". Osiągnąłem to w końcu korzystając z faktu, 
że w JS to co jest po extends może być ... wyrażeniem (!!!).

Czy też sądzicie, że zmienne prywatne to przeżytek?

-- 
Pozdrawiam,
Marek
Re: Nikomu niepotrzebne zmienne prywatne?
#231924
Author: Roman Tyczka
Date: Thu, 25 Jan 2018 20:29
9 lines
984 bytes
On Thu, 25 Jan 2018 20:19:34 +0100, Marek S wrote:

> Czy też sądzicie, że zmienne prywatne to przeżytek?

Czy pisząc zmienne masz na myśli po prostu pola obiektu?

-- 
pozdrawiam
Roman Tyczka
Re: Nikomu niepotrzebne zmienne prywatne?
#231925
Author: Marek S
Date: Thu, 25 Jan 2018 23:07
23 lines
1405 bytes
W dniu 25-01-2018 o 21:29, Roman Tyczka pisze:
> On Thu, 25 Jan 2018 20:19:34 +0100, Marek S wrote:
> 
>> Czy też sądzicie, że zmienne prywatne to przeżytek?
> 
> Czy pisząc zmienne masz na myśli po prostu pola obiektu?
> 

Mam na myśli właściwości (properties).
Dla rozwiania wątpliwości przykład kawałka mojego kodu w PHP:

class tableProClass
{
	private $rowCounter=0;
	private $fnReplace, $fnConvert;
...


Czegoś takiego w klasach JS nie ma.

-- 
Pozdrawiam,
Marek
Re: Nikomu niepotrzebne zmienne prywatne?
#231926
Author: Roman Tyczka
Date: Fri, 26 Jan 2018 22:22
30 lines
1819 bytes
On Fri, 26 Jan 2018 00:07:59 +0100, Marek S wrote:

>>> Czy też sądzicie, że zmienne prywatne to przeżytek?
>> 
>> Czy pisząc zmienne masz na myśli po prostu pola obiektu?
>> 
> 
> Mam na myśli właściwości (properties).
> Dla rozwiania wątpliwości przykład kawałka mojego kodu w PHP:
> 
> class tableProClass
> {
> 	private $rowCounter=0;
> 	private $fnReplace, $fnConvert;
> ...
> 
> 
> Czegoś takiego w klasach JS nie ma.

Dopiero raczkuję w JS, ale jeśli rzeczywiście nie ma pól prywatnych
(property znam z Delphi i z czymś ciutkę innym mi się kojarzą) to w ogóle
nie ma mowy o pełnej obiektowości, bo wszak obiekt to zbiór pól z danymi i
metod do operowania na nich, dzięki czemu uzyskuje się jedną z
fundamentalnych cech OOP czyli enkapsulację. Bez prywatności nie ma
enkapsulacji, bo pola mogą być zmieniane poza logiką obiektu, a to prowadzi
do nieprzewidzianych sytuacji. 

-- 
pozdrawiam
Roman Tyczka
Re: Nikomu niepotrzebne zmienne prywatne?
#231927
Author: Marek S
Date: Sat, 27 Jan 2018 12:24
96 lines
3875 bytes
W dniu 26-01-2018 o 23:22, Roman Tyczka pisze:

>> Czegoś takiego w klasach JS nie ma.
> 
> Dopiero raczkuję w JS, ale jeśli rzeczywiście nie ma pól prywatnych
> (property znam z Delphi i z czymś ciutkę innym mi się kojarzą) 

W nomenklaturze JS zmienne jako cechy obiektów lub też quasiobiektów to 
właściwości:

https://www.w3schools.com/js/js_properties.asp

Jest też gotowa metoda do ich tworzenia zawierająca "properties" w nazwie:

https://developer.mozilla.org/pl/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

> to w ogóle
> nie ma mowy o pełnej obiektowości, bo wszak obiekt to zbiór pól z danymi i
> metod do operowania na nich, dzięki czemu uzyskuje się jedną z
> fundamentalnych cech OOP czyli enkapsulację. Bez prywatności nie ma
> enkapsulacji, bo pola mogą być zmieniane poza logiką obiektu, a to prowadzi
> do nieprzewidzianych sytuacji.

O tym właśnie piszę. Zarówno standard JS (przynajmniej bieżący ECMA6) 
jak i programiści uważają właściwości prywatne chyba jako oldschoolowe. 
JS od dawna ogranicza się jedynie do rezerwacji słów kluczowych typu 
private czy protected ale nic z tym nie robi. Programiści JS, jak wynika 
z moich dyskusji, dziwią się, że coś takiego chcę używać.

Dla Twojej informacji: daje się symulować właściwości prywatne w klasach 
ale wymaga to łamańców. W Googlach grzebałem ze 2 dni i nigdzie 
przykładu poniższego nie znalazłem. Ja wykorzystuję do tego zmienne o 
zasięgu bloku, które deklaruje się słowem kluczowym let (nie var). 
Wykorzystuję też to, że klasę można rozszerzać nie tylko inną klasą, ale 
również - uwaga - wynikiem działania funkcji!!! Trzecia rzecz, korzystam 
z tzw słabych map lub symboli bo w JS właściwość nie musi być aresowana 
stringiem, ale również .... obiektem!

Dopiero taki burdel w kodzie utworzy zmienną prywatną:

let aClass = (function () {
	let a = Symbol("a");

	class aClass {
		readFromA() {
			console.log(this[a], this.b);
		}

		constructor() {
			this[a] = "aaa"; //this is private
			this.b = "bbb"; // this is public
		}

	}

	return aClass;
})();

let bClass = (function () {
	let a = Symbol("a");

	class bClass extends aClass {

		readFromB() {
			console.log("B", this[a], this.b);

		}

		constructor() {
			super();
			this[a] = "ccc"; //this is private
			this.b = "ddd"; // this is public
		}

	}

	return bClass;
})();



let bc = new bClass();
bc.readFromA(); // aaa ddd
bc.readFromB(); // ccc ddd


Wyrażenie "extends aClass" rozszerza klasę bClass o wynik działania 
funkcji anonimowej, który jest przechowywany w zmiennej sugerującej, że 
to klasa aClass a nie zmienna. Funkcja anonimowa zwraca natomiast 
deklarację tak samo nazwanej klasy: czyli aClass.

Super, co?

-- 
Pozdrawiam,
Marek
Re: Nikomu niepotrzebne zmienne prywatne?
#231928
Author: Borys Pogoreło
Date: Sat, 27 Jan 2018 21:59
19 lines
1530 bytes
Dnia Thu, 25 Jan 2018 20:19:34 +0100, Marek S napisał(a):

> 1. Wprowadzono wreszcie pojęcie klas i dziedziczenia ale... zignorowano 
> zmienne prywatne. Nie ma czegoś takiego w samych założeniach.

Bo te klasy i dziedziczenie to tylko opakowanie do dziedziczenia
prototypowego i kopozycji. Ono jest na tyle nietypowe, że zdecydowano się
na takie uproszczenia. A Ty próbujesz podejść JS od strony klas.

> Czy też sądzicie, że zmienne prywatne to przeżytek?

Nie. Ale próbujesz, jak to angole mawiają, porównywać pomarańcze do jabłek.

Zmienne prywatne możesz zasymulować funkcją zwracającą obiekt. Będzie on
nadal mieć dostęp do kontekstu funkcji.

-- 
Borys Pogoreło
borys(#)leszno,edu,pl
Re: Nikomu niepotrzebne zmienne prywatne?
#231929
Author: Marek S
Date: Sun, 28 Jan 2018 14:07
48 lines
3250 bytes
W dniu 27-01-2018 o 22:59, Borys Pogoreło pisze:

>> 1. Wprowadzono wreszcie pojęcie klas i dziedziczenia ale... zignorowano
>> zmienne prywatne. Nie ma czegoś takiego w samych założeniach.
> 
> Bo te klasy i dziedziczenie to tylko opakowanie do dziedziczenia
> prototypowego i kopozycji. Ono jest na tyle nietypowe, że zdecydowano się
> na takie uproszczenia. A Ty próbujesz podejść JS od strony klas.

W JS istnieje wyrażenie class, które zachowuje się odmiennie niż 
dotychczasowe symulowanie klas za pomocą funkcji. Potrafi dziedziczyć po 
innej klasie za pomocą extends w fazie deklaracji (to już wykracza poza 
model kompozycji), posiada operator "super" umożliwiający tworzenie 
odwołań do metod klasy, w przeciwieństwie to funkcji nie obowiązuje 
hoisting, kod klasy zawsze uruchamiany jest w trybie ścisłym, metody 
klasy nie podlegają wyliczeniu, metody klasy nie mają - w odróżnieniu od 
funkcji ich udających - konstruktorów, nie da się wywołać konstruktora 
klasy inaczej niż poprzez new.

Wszystko wskazuje na to, że klasa w JS zbliża się powoli do ich 
odpowiedników znanych w innych językach. Tak, wiem, dziedziczenie jest 
nadal prototypowe, co implikuje ograniczenia. Przypuszczam, że w 
ES8,9,100 w końcu keyword "private" również zostanie wykorzystany, choć 
z protected pewnie problem zawsze będzie.

Dlaczego zatem podejście do klas w JS jako do prawdziwych klas jest 
niewłaściwe?


>> Czy też sądzicie, że zmienne prywatne to przeżytek?
> 
> Nie. Ale próbujesz, jak to angole mawiają, porównywać pomarańcze do jabłek.
> 
> Zmienne prywatne możesz zasymulować funkcją zwracającą obiekt. Będzie on
> nadal mieć dostęp do kontekstu funkcji.

Sęk w tym, że ja nie chcę postępować rodem z ES5 skoro mamy epokę ES6 a 
niebawem ES7. Romanowi pokazałem kod jakiego używam do symulowania 
zmiennych prywatnych korzystając z mechanizmów ES6. Nie chcę go dublować 
w tym wątku - zerknij proszę na moją odpowiedź z 27.01 jemu udzieloną.

Niestety... bez enkapsulacji nadal nie da się obejść problemu. 
Przynajmniej do czasu kiedy moduły nie zaczną w przeglądarkach działać.
Natomiast to co się udało wyeliminować, to zwracanie obiektu przez funkcję.

-- 
Pozdrawiam,
Marek
Re: Nikomu niepotrzebne zmienne prywatne?
#231930
Author: Wojciech Bancer
Date: Sun, 28 Jan 2018 15:14
61 lines
3209 bytes
On 2018-01-28, Marek S <precz@spamowi.com> wrote:
> W dniu 27-01-2018 o 22:59, Borys Pogoreło pisze:
>
>>> 1. Wprowadzono wreszcie pojęcie klas i dziedziczenia ale... zignorowano
>>> zmienne prywatne. Nie ma czegoś takiego w samych założeniach.
>> 
>> Bo te klasy i dziedziczenie to tylko opakowanie do dziedziczenia
>> prototypowego i kopozycji. Ono jest na tyle nietypowe, że zdecydowano się
>> na takie uproszczenia. A Ty próbujesz podejść JS od strony klas.
>
> W JS istnieje wyrażenie class, które zachowuje się odmiennie niż 
> dotychczasowe symulowanie klas za pomocą funkcji.

Nie zachowuje się. To tylko tzw. syntax sugar.
Wszystkie te rzeczy można osiągnąć w ES5, zresztą bez tego nie działałyby
transpilery w rodzaju TypeScript, czy Babela.

> Potrafi dziedziczyć po innej klasie za pomocą extends w fazie deklaracji 
> (to już wykracza poza model kompozycji), posiada operator "super" umożliwiający 
> tworzenie odwołań do metod klasy, w przeciwieństwie to funkcji nie obowiązuje 
> hoisting, kod klasy zawsze uruchamiany jest w trybie ścisłym, metody 
> klasy nie podlegają wyliczeniu, metody klasy nie mają - w odróżnieniu od 
> funkcji ich udających - konstruktorów, nie da się wywołać konstruktora 
> klasy inaczej niż poprzez new.

To co robi "extends", to mniej więcej to co poniżej, tylko w przyjemniejszej
składni.

----
// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',  rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'
----

-- 
Wojciech Bańcer
wojciech.bancer@gmail.com
Re: Nikomu niepotrzebne zmienne prywatne?
#231931
Author: Marek S
Date: Sun, 28 Jan 2018 19:35
37 lines
2658 bytes
W dniu 28-01-2018 o 16:14, Wojciech Bancer pisze:

> Nie zachowuje się. To tylko tzw. syntax sugar.

Ok, skąd czerpiesz tą wiedzę?
Gdy pokaże się nowa wersja standardu "czegoś": CSS, JS, PHP, HTML to 
zawsze zabieram się do analizowania "what's new", zapoznaję się z W3C, 
kupuję w razie potrzeby podręczniki zawierające kompendium zmian etc. 
Sporadycznie spotykam się ze stwierdzeniem, że to tylko syntax sugar, 
jak się wyraziłeś, zamiast rewolucji. Przykładowo w podręczniku 
"ECMASCRIPT 6 - przewodnik po nowym standardzie JS" w rozdziale 9 piszą 
raczej jednoznacznie iż tworzenie klas w ES6 to nowość zrywająca z 
podejściem w ES5, gdzie napisano:

"...ECMAScript 5 wiele bibliotek dostarczało
narzędzia, dzięki którym mogło się wydawać, że JavaScript obsługuje 
klasy. Wprawdzie pewna część programistów była mocno przekonana, że 
język nie potrzebuje klas, ale ilość utworzonych bibliotek 
przeznaczonych do obsługi klas spowodowała dołączenie klas w 
specyfikacji ECMAScript 6."

Skąd zatem takie wypowiedzi? Autor książki nie ma bladego pojęcia o 
świecie więc sobie coś palnął ot tak?

> To co robi "extends", to mniej więcej to co poniżej, tylko w przyjemniejszej
> składni.
> (...) // subclass extends superclass
> Rectangle.prototype = Object.create(Shape.prototype);
> Rectangle.prototype.constructor = Rectangle;

Ponoć właśnie nie do końca. Funkcjonalnie w ES5 owszem. Ale w ES6 i w 
klasach nie da się tego przeprowadzić bo prototype klas jest read only.
Ponoć w tym kierunku będzie rozwój JS prowadzony.

-- 
Pozdrawiam,
Marek
Re: Nikomu niepotrzebne zmienne prywatne?
#231932
Author: Wojciech Bancer
Date: Sun, 28 Jan 2018 21:01
57 lines
3248 bytes
On 2018-01-28, Marek S <precz@spamowi.com> wrote:

[...]

>> Nie zachowuje się. To tylko tzw. syntax sugar.
>
> Ok, skąd czerpiesz tą wiedzę?

Z internetu i przemyśleń własnych :)
Np. z MDNa.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

"JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical-
sugar over JavaScript's existing prototype-based inheritance. The class syntax-
does not introduce a new object-oriented inheritance model to JavaScript."

Czy:
https://stackoverflow.com/questions/36419713/are-es6-classes-just-syntactic-sugar-for-the-prototypal-pattern-in-javascript/36419728
oraz z faktu, że nie mamy pojęcia klasy per se, tylko wszystko jest nadal 
oparte o prototypy.

[...]

> "...ECMAScript 5 wiele bibliotek dostarczało
> narzędzia, dzięki którym mogło się wydawać, że JavaScript obsługuje 
> klasy."

Wydawać? Obsługuje, po prostu w inny sposób (prototype inheritance
vs class inheritance), np:

https://medium.com/javascript-scene/master-the-javascript-interview-what-s-the-difference-between-class-prototypal-inheritance-e4cd0a7562e9

> Wprawdzie pewna część programistów była mocno przekonana, że 
> język nie potrzebuje klas, ale ilość utworzonych bibliotek 
> przeznaczonych do obsługi klas spowodowała dołączenie klas w 
> specyfikacji ECMAScript 6."

Czyli dodali syntax sugar.

> Skąd zatem takie wypowiedzi? Autor książki nie ma bladego pojęcia o 
> świecie więc sobie coś palnął ot tak?

Czemu mnie pytasz?

>> Rectangle.prototype.constructor = Rectangle;
>
> Ponoć właśnie nie do końca. Funkcjonalnie w ES5 owszem. Ale w ES6 i w 
> klasach nie da się tego przeprowadzić bo prototype klas jest read only.
> Ponoć w tym kierunku będzie rozwój JS prowadzony.

Czego się nie da przeprowadzić? Wykonać kodu powyżej np. na node 8?
Da się. Nie da się wywołać konstruktora "klasy" jak zauwazyłeś, ale
to nadal jest jedynie syntax sugar.

-- 
Wojciech Bańcer
wojciech.bancer@gmail.com
Re: Nikomu niepotrzebne zmienne prywatne?
#231933
Author: Marek S
Date: Mon, 29 Jan 2018 18:01
49 lines
2780 bytes
W dniu 28-01-2018 o 22:01, Wojciech Bancer pisze:

>> "...ECMAScript 5 wiele bibliotek dostarczało
>> narzędzia, dzięki którym mogło się wydawać, że JavaScript obsługuje
>> klasy."
> 
> Wydawać? 

No więc ja też z internetu, a konkretnie w tym przypadku - wspomnianej 
książki tą wiedzę czerpię. Jeśli autor zdanie tak sformułował, to ulegam 
przeświadczeniu, że teraz jest inaczej, lepiej. Nie potrafię więc 
zadecydować, które ze sprzecznych (ogólnie teraz mówię, bez nawiązania 
do klas) oficjalnie publikowanych informacji przez wydawnictwa jest 
prawdą, a która fałszem.

>>> Rectangle.prototype.constructor = Rectangle;
>>
>> Ponoć właśnie nie do końca. Funkcjonalnie w ES5 owszem. Ale w ES6 i w
>> klasach nie da się tego przeprowadzić bo prototype klas jest read only.
>> Ponoć w tym kierunku będzie rozwój JS prowadzony.
> 
> Czego się nie da przeprowadzić? 

Modyfikowania prototypu klasy w odróżnieniu od prototypu funkcji.

> Wykonać kodu powyżej np. na node 8?
> Da się. Nie da się wywołać konstruktora "klasy" jak zauwazyłeś, ale
> to nadal jest jedynie syntax sugar.

Strasznie to mętne. "Syntax sugar" tłumaczę sobie jako skrócony zapis 
czego, co przedtem było rozwlekłe.

x=> x+1

zamiast

function cosTam(x) {return x+1;}

Albo Object.assign() zamiast funkcji typu mix-in

Tymczasem jeśli coś zachowuje się inaczej, tak jak np prototypy klas z 
ES6 względem prototypów funkcji z ES5 albo możliwość odwoływania się do 
metod klasy bazowej poprzez "super", to jaki tu cukierek? To nowy 
mechanizm. Tego nie da się zasymulować w ES5.


-- 
Pozdrawiam,
Marek
Re: Nikomu niepotrzebne zmienne prywatne?
#231934
Author: Wojciech Bancer
Date: Mon, 29 Jan 2018 19:12
19 lines
1789 bytes
On 2018-01-29, Marek S <precz@spamowi.com> wrote:

> Tymczasem jeśli coś zachowuje się inaczej, tak jak np prototypy klas z 
> ES6 względem prototypów funkcji z ES5 albo możliwość odwoływania się do 
> metod klasy bazowej poprzez "super", to jaki tu cukierek? To nowy 
> mechanizm. Tego nie da się zasymulować w ES5.

Przecież Ci podałem kod który stanowi odwzorowanie "super".
"Klasa.call(this, 'argument');" ew. "Klasa.prototype.metoda.call(this)"
Da się, tylko syntax jest bardziej paskudny.

https://github.com/addyosmani/es6-equivalents-in-es5#classes

Jakby się czegoś nie dało, to wg Ciebie na jakiej zasadzie 
działałby Babel?

-- 
Wojciech Bańcer
wojciech.bancer@gmail.com
Re: Nikomu niepotrzebne zmienne prywatne?
#231935
Author: Borys Pogoreło
Date: Tue, 30 Jan 2018 19:36
19 lines
1474 bytes
Dnia Mon, 29 Jan 2018 19:01:56 +0100, Marek S napisał(a):

> Strasznie to mętne. "Syntax sugar" tłumaczę sobie jako skrócony zapis 
> czego, co przedtem było rozwlekłe.
> 
> x=> x+1
> 
> zamiast
> 
> function cosTam(x) {return x+1;}

Arrow functions nie są skróconym zapisem, działają nieco inaczej - nie
zmieniają kontekstu.

"Syntax sugar" to np. skrócony sposób tworzenia tablicy.

-- 
Borys Pogoreło
borys(#)leszno,edu,pl
Re: Nikomu niepotrzebne zmienne prywatne?
#231936
Author: Wojciech Bancer
Date: Thu, 01 Feb 2018 21:15
15 lines
1621 bytes
On 2018-01-30, Borys Pogoreło <borys@pl.edu.leszno> wrote:
>> zamiast
>> 
>> function cosTam(x) {return x+1;}
>
> Arrow functions nie są skróconym zapisem, działają nieco inaczej - nie
> zmieniają kontekstu.

Co jest skróconym zapisem mniej więcej takiej postaci:

function (x) {return x+1;}.bind(this);

-- 
Wojciech Bańcer
wojciech.bancer@gmail.com
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