Komunikacja klas

0

Witam,

Poniżej wstawiam przykładowy krótki kod. Znajdują się w nim 3 klasy. Klasa startująca 'program', klasa 'DataBase' oraz klasa 'Client'.

Klasa 'Program' odpala klasę 'DataBase' a w 'DataBase' uruchamiana jest klasa 'Client'.
Pytanie brzmi: Co powinienem wrzucić w kodzie klasy 'Client' by zmienić wartość zmiennej 'public int DataFocus' (należącej do DataBase) ?

Może coś na kształt extern'a z C++? Bardzo proszę o pomoc. Przykłady w kodzie mile widziane ;).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace test
{


    class Client
    {
        // Co tutaj wstawić ?
    }


    class DataBase
    {
        public int DataFocus = 100;     
        
        public DataBase()
        {            
            Client cl = new Client();            
        }        
    }


    class Program
    {
        static void Main(string[] args)
        {            
            DataBase db = new DataBase();
            Console.WriteLine(db.DataFocus);            
        }
    }
}
0
db.DataFocus=200;

A tak w ogóle to lepiej zadeklarować pole DataFocus jako prywatne dataFocus, a wartośc udostępnić przez właściwość DataFocus:

private int dataFacous;
public int DataFocus
{
  get {return dataFocus;}
  set {dataFocus=value;}
}
0
maly186 napisał(a)
db.DataFocus=200;

A tak w ogóle to lepiej zadeklarować pole DataFocus jako prywatne dataFocus, a wartośc udostępnić przez właściwość DataFocus:

private int dataFacous;
public int DataFocus
{
  get {return dataFocus;}
  set {dataFocus=value;}
}

Nie załapałeś chyba problemu z którym piszę :). Chodzi o to że chce z poziomu klasy 'Client' odnieść się do danych zapisanych w klasie 'macierzystej' 'DataBase'.

Innymi słowy: Nie mogę podać polecenia "db.DataFocus=200;" wewnątrz klasy 'Client' ponieważ klasa ta nie wie czym jest db (weź proszę pod uwagę że deklaracja obiektu db jest 'dwie klasy niżej' w klasie 'Program'). Po wpisaniu "db.DataFocus=200;" w segmencie klasy 'Client' kompilator wywala mi błąd.

Koncepcja z właściwościami niestety również nie rozwiązuje problemu.
Powtórzę pytanie: Czy orientuje się ktoś co należy wpisać w ciele klasy 'Client' by odnieść się do zmiennej z innej istniejącej już klasy?. Bardzo proszę o wsparcie. Stoję z pracą już kilka godzin :|.

0

Najprostszym wyjściem jest zawarcie w klasie Client referencji do DataBase. Ewentualnie jeżeli dostęp do pól publicznych to za mało poszukaj sobie o internal. W C# nie ma dokładnego odpowiednika friend z C++

class Client
{
    DataBase dataBase;
    
    public Client(DataBase db)
    {
         dataBase = db;
    }
}

class DataBase
{
    public int DataFocus = 100;     
     
    public DataBase()
    {           
        Client cl = new Client(this);           
    }       
}
0
reVis napisał(a)

Najprostszym wyjściem jest zawarcie w klasie Client referencji do DataBase. Ewentualnie jeżeli dostęp do pól publicznych to za mało poszukaj sobie o internal. W C# nie ma dokładnego odpowiednika friend z C++

class Client
{
    DataBase dataBase;
    
    public Client(DataBase db)
    {
         dataBase = db;
    }
}

class DataBase
{
    public int DataFocus = 100;     
     
    public DataBase()
    {           
        Client cl = new Client(this);           
    }       
}

Dzięki za odpowiedź. Przykład jaki podałeś rozwiązuje troszkę problem, jednakże nie mogę go zastosować u siebie. Powyższy przykład zakłada utworzenie nowego obiektu 'DataBase' wewnątrz klasy 'Client' a oraz skopiowanie do niego (this) całej oryginalnej bazy danych. W ten sposób faktycznie miałbym dostęp do zmiennej DataFocus ustawianej na 20 przy konstrukcji obiektu. Są jednak dwa problemy:

  1. Otrzymuje w ten sposób dwa (różne!) obiekty 'DataBase'. Baza danych ma być do... przechowywania informacji tak więc musi być jedna ;).
  2. W powyższym przykładzie dane są kopiowane. W przypadku DataBase zakładam w chwili obecnej że mogą to być duże obiekty, których kopiowanie może być czasochłonne i niebezpieczne dla całej aplikacji (szczelność/integralność bazy - na czas kopiowania cała aplikacja będzie musiała zostać zatrzymana).

Idealnym rozwiązaniem byłyby tu wskaźniki na obiekt db rodem z C ;]. W C# nie chce się jednak chwytać Garbowanych wskaźników ;]. Troszkę to niebezpieczne i niewygodne jest.

No jak... nie ma naprawdę w C# możliwości przechodzenia wstecz po klasach?

  • Klasa 'Program' widzi i może modyfikować dane klas 'DataBase' i 'Client'
  • Klasa 'DataBase' widzi i może modyfikować dane klasy 'Client'
  • Klasa Client może tylko działać na własnych danych? No absurd! :-/ :|
0

Ten post mnie przeraził. W C# i w większości innych języków obiektowych zmienne obiektowe są wskaźnikiem na właściwy obiekt, czyli kod:

this.dataBase=db

kopiuje tylko referencję do obiektu, a nie sam obiekt. Kopiowanie obiektów to zupełnie inna historia

0

@Mały186, @reVis: Dziękuję bardzo za wsparcie :)
@Mały186: Faktycznie :). Wychodzi brak podstaw w C# ;]. Dopiero zaczynam naukę tego języka.
Jeszcze raz dzięki za szybkie wyjaśnienie problemu... teraz wygląda to strasznie banalnie ;).

Kod podsumowujący:
Wartość wyświetlana pod koniec klasy 'Program' to 200 :).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace test
{
    class Client
    {
        DataBase dataBase;

        public Client(DataBase db)
        {
            dataBase = db;
            dataBase.DataFocus = 200;
        }
    }

    class DataBase
    {
        public int DataFocus = 100;

        public DataBase()
        {
            Client cl = new Client(this);
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            DataBase db = new DataBase();
            Console.WriteLine(db.DataFocus);
            Console.ReadKey();
        }
    }
}
0

Biorąc pod uwagę fakt, że klasa do obsługi bazy ma być tylko jedna to może zainteresuj się wzorcem projektowym Singleton. Wtedy takie przekazywanie referencji będzie zbędne :) A raczej ten sposób przekazywania referencji.
http://www.yoda.arachsys.com/csharp/singleton.html
A w klasie Client możesz napisać:

public Client()
{
    dataBase = DataBase.Instance;
}

Przy czym zagwarantowane masz, że w czasie działania programu powstanie dokładnie jedna instancja klasy obsługi bazy.

0

Czy nie dałoby się tego zrobić w równie prosty sposób ,ale nie korzystając z konstruktorów ?

0

@up

A co jest zlego w konstruktorach?

0

Nic. Jednak co zrobić gdy np. mamy 2 formy i chcemy,by wartosc pola w 1 zmieniła się dopiero gdy np wpiszemy jakis tekst w textBox lub klikniem przycisk drugiej formy. Konstruktorem zmienimy ta wartosc od razu po wyswietleniu okna, wiec musi byc jakas inna droga.

0

Rece mi juz opadaja. Problem komunikacji miedzy formularzami byl juz tyle razy poruszany i to w dodatku kilkukrotnie w ciagu ostatnich dni.

Chyba arta napisze na ten temat i spokoj bedzie :-P

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