Każda klasa może widzieć prywatne pola w innych jej instancjach?

0

Zaczynam naukę C#.
Czytam o dostępie do prywatnych pół i metod.
Nie mogę zrozumieć tego zdania:
Każda klasa może widzieć prywatne pola w innych jej instancjach?
Może inaczej, zdanie rozumiem ale nie mogę sobie tego jakoś wyobrazić!
Mam dwie instancje klasy człowiek: tomek i janek.
Klasa człowiek ma prywatne pole wiek.
Jak obiekt tomek może odczytać wiek janka?

3

Klasa może mieć taką metodę:

class Czlowiek
{
  private int wiek;

  int GetWiek(Czlowiek czlowiek)
  {
    return czlowiek.wiek;
  }
}

I potem możesz zrobić:

tomek.GetWiek(janek)

i zwróci wiek janka

3
using System;
					
public class Program
{
	public static void Main()
	{
		var tomek = new Person("Tomek");
		var janek = new Person("Janek");
		tomek.PrintPersonName(janek);
		// Console.WriteLine(tomek.name); // inaccessible due to protection level
	}
}

public class Person{
	private string name;
	
	public Person(string name){
		this.name = name;
	}
	
	public void PrintPersonName(Person other){
		Console.WriteLine($"My name: {this.name}");
		Console.WriteLine($"Other name: {other.name}");
	}
}

https://dotnetfiddle.net/hNGqW9

2
mako12 napisał(a):

Nie mogę zrozumieć tego zdania:
Każda klasa może widzieć prywatne pola w innych jej instancjach?

Ja też go nie mogę zrozumieć, to jest bardzo dziwne zdanie. Klasa nie widzi pól. Klasa to tylko definicja tego, co jej instancja (czyli obiekt) może robić. To obiekty mogą widzieć pola innych obiektów.

Klasa człowiek ma prywatne pole wiek.
Jak obiekt tomek może odczytać wiek janka?

Skoro pole jest prywatne, to właśnie o to chodzi, żeby nie odczytał.

0

Zacytowane zdanie pochodzi z książki Rusz głową c#. Rozdział 5 dotyczy hermetyzacji. Odnoszę wrażenie że, polskie tłumaczenie jest niejasne i niedokładne.
Po zapoznaniu się z całym rozdziałem myślę, że zdanie to powinno brzmieć tak:** Każdy obiekt (instancja) dowolnej klasy może widzieć prywatne pola innej instancji tej samej klasy.** Czyli jeśli mamy dwie instancje tej samej klasy to jeden obiekt może bez problemy odczytać prywatne pole drugiego obiektu tej samej klasy. Byłem przekonany że może to zrobić jakoś "bezpośrednio" a nie za pomocą publicznej metody. Za pomocą publicznej metody to obiekty dwóch różnych klasy mogą odczytać pole prywatne obiektu innej klasy więc to żaden sukces. Obiekt klasy Człowiek może odczytać prywatne pole obiektu Pojazd jeśli ma publiczną metodę która to umożliwia.
To co napisałem to tylko mój sposób zrozumienia tego co czytam i próba zrozumienia co mogą więcej wiedzieć o sobie dwa obiekty tej samej klasy w odróżnieniu od obiektów dwóch różnych klas. Czy obiekty tej samej klasy łączy coś co pozwala im odczytywać pola prywatne jeden drugiemu a nie mają tej możliwości dwa obiekty dwóch różnych klas?

0

A przypadkiem nie chodzi o statyczną zmienną w klasie? Taka będzie wspólna dla wszystkich instancji. O innym 'widzeniu' nie ma mowy, a co najwyżej o zwróceniu wartości przez metodę.

0

strona 226 Rozdział 5 Rusz głową c# wydanie drugie

tak to wygląda w książce. Proszę czytać od nr 1 do nr 3

0

No jak dla mnie to to jest not even wrong. Klasa i instancja istnieją w zupełnie różnych wymiarach, klasa nie może widzieć niczego w instancji, to wyrażenie jest tak nieprecyzyjne, że niczego nie oznacza. Co to w ogóle znaczy, że klasa widzi, albo że instancja widzi? Jak można widzieć pole w instancji, skoro pole to coś co istnieje na poziomie klasy, w przypadku instancji więcej sensu ma mówienie o wartościach, a nie polach.

Prawdopodobnie chodzi o to, co pokazał na przykładzie @Afish, ale to by należało ująć np.: metoda klasy ma dostęp do prywatnych składowych instancji tej klasy przekazanej jako argument, żeby miało to jakiś sens.

0

To prawda, że jest mowa o uzyskaniu dostępu do wartości prywatnych pól przez metody publiczne ale nie dla wszystkich!! na stronie nr 3 wyraźnie jest napisane że
że koledzy ciaAgenta czyli kolejne instancje klasy SecretAgent widzą swoje pola prywatne bez użycia publicznej metody AgentGreeting() Tak jak to rozumiem. Proszę dokładnie przeanalizować tekst podkreślony na czerwono. Proszę dokładnie przeczytać to co jest zakreślone w "kółku" - "Tylko inny obiekt ciaAgnet może je widzieć (widzieć rozumiem, że może je bezpośrednio odczytać, że ma do nich dostęp bezpośredni)

0

Przeanalizowałem tekst podkreślony na czerwono. I jak stwierdziłem wyżej, jest tak bełkotliwy i nieprecyzyjny, że nie ma sensu go interpretować.
A ciaAgent to nie klasa tylko obiekt klasy SecretAgent.

3

Strasznie dużo tu rozkmin i czepiania się zdania wyrwanego z kontekstu, który (kontekst) jasno sugeruje, co autor miał na myśli.

Weźmy taki kod:

class Class {
    private int Field;
}

Klasa Class z jednym polem Field o widoczności private. Widoczność pola (w ogólności składowej) oznacza, że mając instancję

Class instance = new Class();

mogę kontrolować, kto i jak może zrobić instance.Field. Jeżeli pole jest widoczne, to znaczy, że instance.Field się skompiluje, jeżeli nie jest, to się nie skompiluje.

private na polu znaczy tyle, że tylko składowe tej klasy widzą to pole. To znaczy, że tylko "z wnętrza klasy" można zrobić instance.Field. "Z wnętrza" oznacza tutaj "z ciał metod będących składowymi klasy Class" (1). Weźmy taką metodę:

void Foo(){
    Console.WriteLine(instance.Field);
}

Teraz pytanie, jak zmienić i gdzie umieścić tę metodę, żeby kod się skompilował. Skoro pole jest prywatne, to są 3 opcje:

  1. Metoda może być metodą instancji klasy i używać this:
void InstanceFoo(){
    Console.WriteLine(this.Field);
}
  1. Metoda może być metodą instancji klasy i używać referencji:
void OtherInstanceFoo(Class instance){
    Console.WriteLine(instance.Field);
}
  1. Metoda może być metodą klasy (metodą statyczną) i używać referencji:
static void ClassFoo(Class instance){
    Console.WriteLine(instance.Field);
}

Jeżeli umieścimy instance.Field poza składowymi klasy Class, to kod się nie skompiluje.

O ile przypadek pierwszy jest oczywisty — biorę instancję instance i wywołuję instance.InstanceFoo(), to metoda InstanceFoo() widzi prywatne pole tej instancji — o tyle pozostałe dwa przypadki są dla wielu programistów zaskoczeniem (nawet swego czasu zadawałem to pytanie na rekrutacjach i masa „seniorów” nie ogarniała). private nie oznacza, że pole jest prywatne dla instancji. Oznacza tylko, że pole nie jest widoczne poza składowymi tej klasy (2). Czyli możemy też zrobić coś takiego:

void CreateNewInstanceAndAccessPrivateField(){
    Class instance2 = new Class();
    Console.WriteLine(instance2.Field);
}

Zaskakujące dla wielu jest to, że jeżeli jest to składowa klasy Class (to jest logicznie równoważne drugiemu przypadkowi), to wykonując tę metodę na instancji instance (czyli metoda wykonuje się w kontekście instance, czyli this wskazuje na instance) mogę zrobić instance2.Field. Ludzie myślą, że skoro moim this-em jest instance a nie instance2, to nie widzę prywatnych pól instance2, ale to nie jest prawda. Ale jeżeli tę metodę umieszczę poza klasą Class, to już ten kod się nie skompiluje.

Ograniczenie dostępu tylko do instancji da się uzyskać w niektórych językach, ale nie w C#.

Jak ktoś chce kompilować, to https://dotnetfiddle.net/oM2ENa

Teraz odnośnie przerzucania się definicjami i znaczeniem zdania: Każda klasa może widzieć prywatne pola w innych jej instancjach — precyzyjniej byłoby powiedzieć Każda składowa klasy może widzieć prywatne pola w dowolnej instancji tej klasy, ale pierwotne zdanie jest osadzone w kontekście, który raczej jasno sugeruje, co autor miał na myśli, nawet nagłówek mówi dostęp do prywatnych pól i metod można uzyskać tylko z wnętrza klasy.

(1) Lub wyrażeń w ogólności, ale one są kompilowane do metod.
(2) Tu można rozpocząć dyskusje o różnicy między typem a klasą, ale w C# jest to równoważne dla reference types. W ogólności nie jest, wtedy oczywiście widoczność jest definiowana inaczej.

0

Zdanie które przytoczyłem w tytule nie jest wyrwane z kontekstu jest ważnym zdaniem w podsumowaniu rozdziału książki na temat dostępu do prywatnych pól i metod i wyraźnie sugeruje że koledzy agenta ciaAgent mają" łatwiej".
Może od początku.
w przykładzie są trzy instancje (obiekty) trzech różnych klas.

  1. ciaAgent jest instancją klasy SecretAgent (agent USA)
  2. kgbAgent jest instancją klasy EnemyAgent (agent ZSRR)
  3. mi5Agent jest instancją klasy BritishAgent (agent UK)

Klasa SecretAgent ma publiczną metodę AgentGreeting() której używają agenci ZSRR i agenci UK do odczytania prywatnego pola agenta USA.
Jeśli znają hasło to dzięki tej publicznej metodzie mają dostęp do prywatnego pola z prawdziwym imieniem i nazwiskiem agenta USA. Tej samej metody mogą użyć też koledzy agenta USA czyli kolejne instancje klasy SecretAgent. Ta publiczna metoda jest dla wszystkich!! Ale autor pod koniec rozdziału wyraźnie pisze że koledzy ( zaprzyjaźnieni szpiedzy agenta USA czyli kolejne instancje SecretAgent nie muszą tej publicznej metody używać bo " widzą bez tej metody wszystko".
Cytat z książki:
O ile kgb (czyli agent ZSRR)** i mi5** (czyli agent UK) muszą użyć metody AgentGreeting() (w celu odczytania pola prywatnego agenta USA), to zaprzyjaźnieni szpiedzy (czyli kolejne instancje klasy SecretAgent)** mogą widzieć wszystko** ( rozumiem nie muszą użyć tej metody)** - każda klasa może widzieć prywatne pole w innej jej instancji.** (Koniec cytatu)

Poniżej tego tekstu w książce jest rysunek (zobacz nr 3) gdzie po prawej stronie ponownie jest coś takiego:
mi5Agent ( czyli agent UK) jest instancją klasy BritishAgent, więc także nie ma dostępu do prywatnych pól ciaAgenta (agenta USA). i poniżej znowu zaskakujące stwierdzenie:** Tylko inny obiekt ciaAgent może je widzieć.**

Z tego co koledzy piszą wcześniej to wynika że nic więcej nie widzi i że to błąd.
Kolega czyli kolejna instancja agenta USA musi użyć metody publicznej AgentGreeting() tej samej co "wrogowie" z innych klas - czyli to żaden sukces albo dla kolegów trzeba umieścić kolejną metodę publiczną która będzie jako parametr przyjmować referencje do obiektów typu ciaAgent. Czy tak?

0

Załóżmy, że każdy typ agentów ma metodę GetCiaRealName(CiaAgent ciaAgent), która chce pobrać prawdziwe imię agenta podanego w parametrze. U kgb i mi5 nie można dobrać się do prywatnej składowej tej klasy, gdyż są to inne typy, więc jedyną opcją jest wywołanie metody "AgentGreeting"

Więc metoda "GetCiaRealName" powinna wyglądać mniej więcej tak:

public void GetCiaRealName(CiaAgent ciaAgent)
	{
		Console.WriteLine(ciaAgent.AgentGreeting("jakisString"));
	}

Implementacja tej metody w klasie "CiaAgent" może wyglądać :

public void GetCiaRealName(CiaAgent ciaAgent)
	{
		Console.WriteLine(ciaAgent.realName);
	}

Gdyż parametr jest takiego samego typu jak klasa w której ta metoda jest zaimplementowana.
Private oznacza, że składowa jest widoczna jedynie w danej klasie.

0
Afish napisał(a):

Strasznie dużo tu rozkmin i czepiania się zdania wyrwanego z kontekstu, który (kontekst) jasno sugeruje, co autor miał na myśli.

@Afish - to wszystko, co piszesz, to jest oczywiście prawda. Tylko zdajesz się nie zauważać jednej rzeczy - gdyby w książce faktycznie wszystko było takie jasne, to ten wątek by nie powstał. A jednak istnieje.
I ja się wcale nie dziwię, że @mako12 ma problem ze zrozumieniem tego, bo autorzy książki w niejasny sposób żonglują pojęciami, wyrażają się nieprecyzyjnie i sam musisz pisać pisać elaboraty, żeby podać prawidłową interpretację.

0

To może ja dodam trochę kontekstu, ale posługując się porównaniem do Scali :]

W Scali oprócz private, private[Typ] i private[paczka] można mieć też private[this] (szczegóły, np: https://www.jesperdj.com/2016/01/08/scala-access-modifiers-and-qualifiers-in-detail/ ).
Do pola private[this] może odwołać się tylko instancja, w skład której wchodzi to pole. Przykład https://www.ideone.com/SLazpg :

	class Privates {
		private val a: Int = 5;
		private[this] val b: String = "aaa";
 
		def equalsByA(that: Privates): Boolean =
			a == that.a // to przechodzi, bo a to zwykłe private
 
		def equalsByB(that: Privates): Boolean =
			b == that.b // błąd kompilacji, bo private[this] uniemożilwia dostęp do pola z innej instancji
	}

Być może autorowi stwierdzenia z tytułu wątku chodziło właśnie o takie rozróżnienie.

0
somekind napisał(a):

autorzy książki w niejasny sposób żonglują pojęciami, wyrażają się nieprecyzyjnie i sam musisz pisać pisać elaboraty, żeby podać prawidłową interpretację.

Nikt w tym temacie nie wyrażał się precyzyjnie (Ty również stosowałeś uproszczenia tłumacząc się rzekomym brakiem sensu niektórych przypadków). Moim zdaniem opis w książce jest wystarczająco zrozumiały (szczególnie, że jest to książka dla początkujących, a nie publikacja naukowa) i w tym temacie jest dużo czepialstwa, ale oczywiście to tylko opinia.

Poza tym, ja napisałem elaborat nie w celu wyjaśnienia zdania z książki, tylko aby objaśnić mechanizm. Jak już wspomniałem, na rekrutacjach wielu seniorów kreuje się na bardzo doświadczonych, ale private i protected często pokazuje prawdę.

0
Afish napisał(a):

Nikt w tym temacie nie wyrażał się precyzyjnie (Ty również stosowałeś uproszczenia tłumacząc się rzekomym brakiem sensu niektórych przypadków).

To, że moja definicja była zawężona do problemu omawianego w wątku, to nie znaczy, że nie była precyzyjna. Ty podałeś precyzyjną definicję ogólną, tak więc bez przesady z tym, że "nikt".

Moim zdaniem opis w książce jest wystarczająco zrozumiały (szczególnie, że jest to książka dla początkujących, a nie publikacja naukowa) i w tym temacie jest dużo czepialstwa, ale oczywiście to tylko opinia.

A rzeczywistość, którą obserwujemy jest taka, że ta "wystarczająco zrozumiała" książka sprawia problem początkującemu.

Poza tym, ja napisałem elaborat nie w celu wyjaśnienia zdania z książki, tylko aby objaśnić mechanizm. Jak już wspomniałem, na rekrutacjach wielu seniorów kreuje się na bardzo doświadczonych, ale private i protected często pokazuje prawdę.

Spytaj o sealed, to polegną nawet principale. ;)

0

Chora książka, mimo obrazków (jeśli dla kogoś obrazki są zaletą). Dla nikogo, ani dla początkujących, ani dla zaawansowanych

1 użytkowników online, w tym zalogowanych: 0, gości: 1