Wątek zablokowany 2015-06-29 23:52 przez furious programming.

Przekazywanie zmiennych pomiędzy klasami

0

Witajcie,
postanowiłem zacząć uczyć się języka C# ale mam problem z jednym zagadnieniem. Otóż mam klasę z kilkoma zmiennymi i drugą klasę w której zmienne z pierwszej chce wykorzystać. Chce, aby wartości tych zmiennych były tam zmieniane, tak aby klasa 1 operowała potem na nowych wartościach. Jak to zrobić?
Tworzę obiekt 1 klasy w klasie 2 ale wtedy kompilator zgłasza błędy bo jakaś zmiennaX nie istnieje w kontekście 2 klasy.
Prosiłbym aby ktoś wyjaśnił mi to prostym językiem.
Pozdrawiam i z góry dziękuję

0

Kiedy tworzysz zmienną zmienną w klasie 1, to musisz napisać coś takiego:

public int zmienna = 0;

zamiast

int zmienna = 0;

Wtedy możesz w klasie 2 zrobić coś takiego:

klasa1.zmienna = 3;

Kiedy nie używasz słowa public, to zmienna jest domyślnie traktowana przez kompilator jako prywatna i nie można się do niej odwołać z klasy 2.

0

Możesz wrzucić fragment kodu?

0

A jak wygląda sposób na uzyskane tego samego efektu, ale bez modyfikatora public? Musimy się przecież starać aby nasz kod był maksymalnie niepubliczny

0

W klasie1 tworzysz publiczne metody operujące na tych zmiennych (chyba o pola Ci chodzi w tym momencie?). Obiekt klasy1 przekazujesz w konstruktorze do klasy2 i zapisujesz go w polu klasy2. W metodach klasy2 możesz teraz wywoływać metody klasy1, dzięki czemu możesz zmieniać interesujące Cię wartości, a klasa1 będzie dalej operować na zmienionych.

0

Tak, z tego co wyczytałem rzeczywiście chodzi mi o pola;-)

somekind napisał(a):

Obiekt klasy1 przekazujesz w konstruktorze do klasy2 i zapisujesz go w polu klasy2.

Czy mógłbyś mi to jaśniej przekazać? Może pokazać kawałek jakiegoś kodu. Byłbym bardzo wdzięczny.

0
Klasa2
{
    Klasa1 klasa1;

    public Klasa2(Klasa1 klasa1)
    {
        this.klasa1 = klasa1;
    }
}

I teraz w kodzie Klasa1:

var k2 = new Klasa2(this);
0
 
   class Program
    {
        public int zmienna = 5;
        public int liczba = 6;

        static void Main(string[] args)
        {
            Program klasa1 = new Program();
            klasa1.Wyswietl();
        }

        void Wyswietl()
        {
            var k2 = new Obliczenia(this);
            k2.WykonajObliczenia();
            if (zmienna == 6) Console.WriteLine("zmienna == 6");
            if (liczba == 7) Console.WriteLine("liczba == 7");

            var InObl = new InneObliczenia(this);
            InObl.NoweObliczenia2();
            Console.WriteLine(liczba);
            Console.ReadKey();
        }
    }

    class Obliczenia
    {
        public int tempLiczba = 1;
        Program programik;
        public Obliczenia(Program programik)
        {
            this.programik = programik;
        }

        public void WykonajObliczenia()
        {
            programik.zmienna = 5  + 1;
            var InO = new InneObliczenia(this);
            InO.NoweObliczenia();
            programik.liczba = tempLiczba;
        }
    }

    class InneObliczenia
    {
        Obliczenia obliczenia;
        public InneObliczenia(Obliczenia obliczenia)
        {
            this.obliczenia = obliczenia;
        }
        Program programik;
        public InneObliczenia (Program programik)
        {
            this.programik = programik;
        }
        public void NoweObliczenia()
        {
            obliczenia.tempLiczba = obliczenia.tempLiczba + 6 ;
        }
        public void NoweObliczenia2()
        {
            programik.liczba += 10;
        }
    }

Na podstawie wskazówek zbudowałem coś takiego. Wynik mnie satysfakcjonuje otrzymałem to co chciałem czyli w kolejnych liniach
zmienna == 6
zmienna == 7
17
Czy to co napisałem jest poprawne? Chodzi mi głównie o ostatnią klasę. Metody w niej zawarte wywołuje zarówno z klasy Obliczenia jak i Program. Dlatego umieściłem tam 2 kostruktory. Czy zrobiłem to poprawnie?

0

Pomogłoby gdybyś podał treść zadania, bo jak dla mnie cały program nie ma sensu.

0

nie ma treści zadania. Tworze program aby się zrozumieć to.
Założyłem, że w klasie Program będę miał jakieś pola. Następnie wywołam metody z innych klas które będą operować na polach klasy Program. w taki sposób, że będą zmieniać ich wartość.

0

Generalnie to zmienna i liczba w Program to powinny być właściwości, a nie publiczne pola, zaś InneObliczenia powinna zostać rozbita na dwie klasy.

A tak w ogóle, to w tym przypadku żadnych konstruktorów nie powinno być, wystarczy jedna klasa z trzema statycznymi metodami.

0

@moriss, odpowiedź na Twoje pytanie z komentarza brzmi: "to zależy". W ogólności, przekazuje się jedne obiekty do innych, aby wykonywać jakieś operacje na nich. Ale to, co Ty napisałeś jakiś abstrakcyjny przykład, który jest nierealistyczny, więc trudno tutaj pisać o tym jak powinno być. Podaj jakiś prawdziwy kod, to będzie można Ci konkretnie odpowiedzieć.

Generalnie w dobrym kodzie:

  1. Klasa służy jednemu celowi, czyli klasa służąca do obliczeń nie wyświetla niczego na ekranie i odwrotnie. Klasa pomocnicza dla klasy X nie jest klasą pomocniczą dla klasy Y. Klasa przechowująca wynik jakiejś operacji nie jest klasą wykonującą tę operację.
  2. Metoda wykonuje jedną rzecz, czyli metoda wyświetlająca wynik na ekranie niczego nie oblicza.
  3. Stan klas powinien być niezmienny, tzn. po utworzeniu obiektu danej klasy nie zmieniamy wartości jego pól.

A klasa Program to punkt startowy aplikacji, nie umieszcza się w niej pól, nie trzyma wyników, nie tworzy jej obiektów.

0

W większości rozumiem, mam tylko pytanie co do klasy głównej - nie tworzy się jej obiektów itd. Czyli w klasie głównej powinno znajdować się tylko utworzenie obiektu innej klasy, wywołanie metody. Wszelkie czynności powinny się odbyć poza nią?

Teraz następne pytanie. Jeśli będę używał konstruktory jak @somekind zaproponował ale będę chciał udostępnić więcej pól bo np 20 to co wtedy? Wydaje się to mniej wygodne.
Jest jakiś inny sposób na przekazanie większej ilości zmiennych?

0
moriss napisał(a):

W większości rozumiem, mam tylko pytanie co do klasy głównej - nie tworzy się jej obiektów itd. Czyli w klasie głównej powinno znajdować się tylko utworzenie obiektu innej klasy, wywołanie metody. Wszelkie czynności powinny się odbyć poza nią?

Niekoniecznie. W prostej aplikacji konsolowej, w klasie Program można umieścić statyczne metody odpowiedzialne za wyświetlanie menu, pobieranie danych od użytkownika i wyświetlanie mu wyników działania programu.

Teraz następne pytanie. Jeśli będę używał konstruktory jak @somekind zaproponował ale będę chciał udostępnić więcej pól bo np 20 to co wtedy? Wydaje się to mniej wygodne.

Po pierwsze, to nie udostępniaj pól tylko metody, które na nich operują.

Jest jakiś inny sposób na przekazanie większej ilości zmiennych?

Opakować je w klasę.

Po drugie ja chyba piszę mało zrozumiale - przez konstruktory przekazujesz do klasy obiekty klas, które "pomagają" jej wykonać jej zadania. Np. do klasy tworzącej koszyk klienta sklepu internetowego przekazujesz obiekt klasy pozwalającej na dostęp do bazy produktów danego sklepu.

Natomiast, jeśli chcesz przekazać z metody klasy A, do metody klasy B jakieś dane, na których ma ona operować, to po prostu przekazujesz te zmienne (albo bezpośrednio, albo opakowujesz je w obiekt klasy X), nie musisz przekazywać całego obiektu klasy A.

0

Przekazujesz bezpośrednio - chodzi ci o podanie ich jako parametry formalne metody?
Czy mógłbyś mi przybliżyć termin "opakować"?

Pozdrawiam

0
moriss napisał(a):

Przekazujesz bezpośrednio - chodzi ci o podanie ich jako parametry formalne metody?

Raczej argumenty wywołania. Parametry formalne definiuje się podczas definiowania metody

Czy mógłbyś mi przybliżyć termin "opakować"?

Utworzyć klasę, która będzie zawierała wartości, które chcesz przekazać do metody. Czyli zamiast:

 
void JakaśFunkcja(int id, string opis, double kwota)
{
    // ...
}

JakaśFunkcja(101, "podwyżka za nadgodziny", 123.45);

mamy:

 
class DanePodwyżki
{
    public int Id { get; private set; }
    public string Opis { get; private set; }
    public double Kwota { get; private set; }

    public DanePodwyżki(int id, string opis, double kwota)
    {
        this.Id = id;
        this.Opis = opis;
        this.Kwota = kwota;
    }
}

void JakaśFunkcja(DanePodwyżki danePodwyżki)
{
    // ...
}

var danePodwyżki = new DanePodwyżki(101, "podwyżka za nadgodziny", 123.45);
JakaśFunkcja(danePodwyżki);
0

nie do końca widzę sens opakowywania. Robię to, aby uniknąć zapis takiej sytuacji

void MojaMetoda(wieleparmetrów)
{
//...
}
 

a i tak będę musiał tworzyć metodę która jako parametry przyjmie te wszystkie wartości których nie chciałem wpisywać do MojaMetoda. Chyba, że zbyt płytko myślę

0
class DanePodwyżki
{
    public int Id { get; private set; }
    public string Opis { get; private set; }
    public double Kwota { get; private set; }
 
    public DanePodwyżki()
    {
        Id = 0;
        Opis = "";
        Kwota = 0;
    }
}
 
void JakaśFunkcja(DanePodwyżki danePodwyżki)
{
    // ...
}
 
var danePodwyżki = new DanePodwyżki();
danePodwyżki.Id=101;
danePodwyżki.Opis="podwyżka za nadgodziny";
danePodwyżki.Kwota=123.45;
JakaśFunkcja(danePodwyżki);

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