Problem z przekazywaniem wartości w obiektach

0

Hej ponownie.
Z ostatnich moich wątków wiecie, że od niedawna zacząłem sobie powtarzać programowanie i dzisiaj zacząłem programowanie obiektowe, z którego nigdy wcześniej nie korzystałem i mam niemały problem przyznam.

Otóż mam zadanie takie:
Zdefiniuj typ obiektowy Prostokat, o polach a i b: Real przedstawiających długość boków i metodach:

  • procedure Wczytaj
  • function Pole
  • function Obwod
  • procedure Wyswietl
program Zad1Str42;

uses
  Crt;
type
   TProstokat = object
     A, B : Real;
     procedure Wczytaj;
     function Pole(var C: Real; var D:Real) : Real;
     function Obwod(var C: Real; var D: Real) : Real;
     procedure Wyswietl;
   end;

procedure TProstokat.Wczytaj;
begin
  Write('Podaj bok a ');
  ReadLn(A);
  Write('Podaj bok b ');
  ReadLn(B);
  Pole(A, B);
end;

function TProstokat.Pole(var C: Real; var D:Real) : Real;
begin
  Result := C*D;
end;

function TProstokat.Obwod(var C: Real; var D:Real) : Real;
begin
  Result := 2*A+2*B;
end;

procedure TProstokat.Wyswietl;
begin
  WriteLn('Pole prostokata wynosi ', Pole(A, B):0:2);
 	WriteLn('Obwod prostokata wynosi ', Obwod(A, B):0:2);
end;

var
  X : TProstokat;
  Pole : TProstokat;

begin
  TextColor(15);
		TextBackground(1);
  ClrScr;
  X.Wczytaj;
  ReadLn();
end.

Nie wiem jak przekazać wartość z funkcji Pole i Obwod pod te pola A i B. Domyślam się, że to banalny problem, ale nie wiem jak już to ugryźć.

0

Trochę ta klasa nie ma sensu – w koncu pola A i B (nazwy z tyłka – popraw) są publiczne, więc dostępne z zewnątrz. Po drugie, skoro masz przewidziane metody przeprowadzające obliczenia, to powinny one być proceduralne i aktualizować wartości pól obiektu. Po trzecie, wprowadzanie danych z klawiatury nie powinno być funkcjonalnością obiektu przechowującego dane, więc wywal metodę Wczytaj. Zresztą metoda Wyswietl też nie powinna się w tej klasie znajdować.

Poczytaj trochę o hermetyzacji.

0

Wybacz, ale nie rozumiem Twojej odpowiedzi za bardzo. Nazwy procedur, funkcji i pól są z książki i chciałbym to zadanie zrobić tak jak jest w książce.
Co znaczy, że metody powinny być proceduralne?

0
soob napisał(a):

Nazwy procedur, funkcji i pól są z książki i chciałbym to zadanie zrobić tak jak jest w książce.

Jeśli takich rzeczy książka nie wyjaśnia to ją po prostu wyrzuć. Tym bardziej, jeśli kod który wkleiłeś w swoim poscie z tej książki pochodzi – no nie nadaje się do niczego, jeśli takie przykłady podają.

Co znaczy, że metody powinny być proceduralne?

Że powinny być procedurami należącymi do danej klasy. A procedury i funkcje należące do danej klasy nazywamy właśnie metodami. Mogą one być proceduralne (nie zwracające danych w rezultacie) lub funkcyjne (zwracające dane w rezultacie).

0

Kod jest mój. Ćwiczenie jest z książki. Niestety nie było jeszcze nic o klasach dlatego mam problem zrozumieć to co piszesz. Chyba, że klasa to to samo co obiekt, bo miałem rekordy i obiekty. W książce mam takie zdanie:

"Procedury i funkcje zadeklarowane w obiekcie nazywają się metodami

0

Metodą jest dowolna funkcja lub procedura zadeklarowana wewnątrz innego ”elementu”, czyli wewnątrz klasy, obiektu (starego obiektu, nie jako instancji klasy) lub rekordu. Wszystko co zadeklarowane jest luzem w danym module nie jest metodą. Poniekąd, ale nie chcę Ci mieszać w głowie.

Nie wiem co konkretnie ma robić ten Twój program, ale obiekt TProstokat nie powinien zawierać metod pobierających dane z konsoli ani w niej te dane wyświetlających. Dane dotyczące Twojego prostokąta powinieneś pobrać w innej części programu i je przekazać do obiektu, np. za pomocą konstruktora lub za pośrednictwem właściwości.

0

Zrobiłem to zadanie tak jak napisano w książce. Rozumiem, że to może nie być optymalny sposób rozwiązaywania takich rzeczy, ale rozumiem też, że książka ma nauczyć jakiś podstaw i pozwolić zrozumieć na czym polegają te obiekty, bo przyznam, że czasem nie bardzo rozumiem dlaczego taki sposób jest lepszy od takiego tradycyjnego. Niestety nie umiem chyba przekazywać danych do obiektu tak jak prosiłeś - ciągle wyskakiwał mi jakiś błąd.

Mógłbyś sprawdzić ten kod?

program Zad1Str42;

uses
  Crt;
type
   TProstokat = object
     Bok1 : Real;
     Bok2 : Real;
     procedure Wczytaj;
     function Pole : Real;
     function Obwod : Real;
     procedure Wyswietl;
   end;

procedure TProstokat.Wczytaj;
begin
  Write('Podaj bok A ');
  ReadLn(Bok1);
  Write('Podaj bok B ');
  ReadLn(Bok2);
end;

function TProstokat.Pole : Real;
begin
  Result := Bok1*Bok2;
end;

function TProstokat.Obwod : Real;
begin
  Result := 2*Bok1+2*Bok2;
end;

procedure TProstokat.Wyswietl;
begin
  WriteLn('Pole prostokata wynosi ', Pole:0:2);
  WriteLn('Obwod prostokata wynosi ', Obwod:0:2);
end;

var
  Prostokat : TProstokat;

begin
  TextColor(15);
  TextBackground(1);
  ClrScr;
  Prostokat.Wczytaj;
  Prostokat.Pole;
  Prostokat.Obwod;
  Prostokat.Wyswietl;
  ReadLn();
end.
0

Kod wygląda Ok i działa prawidłowo, ale nie jest dobry, bo obiekt prostokąta zawiera logikę, której zawierać nie powinien. Mowa o metodach Wczytaj i Wyswietl – takimi rzeczami nie powinien zajmować się obiekt, a powinny one być wykonane w osobnych procedurach otrzymujących w parametrze ten obiekt.

Zobacz na poniższy przykład:

uses
  Crt;

type
  TRectangle = object
    SideA: Real;
    SideB: Real;
    function Field(): Real;
    function Perimeter(): Real;
  end;

  function TRectangle.Field(): Real;
  begin
    Result := SideA * SideB;
  end;

  function TRectangle.Perimeter(): Real;
  begin
    Result := 2 * SideA + 2 * SideB;
  end;

  procedure LoadRectangleData(out ARectangle: TRectangle);
  begin
    Write('Enter side A size: ');
    ReadLn(ARectangle.SideA);

    Write('Enter side B size: ');
    ReadLn(ARectangle.SideB);
  end;

  procedure ShowRectangleData(const ARectangle: TRectangle);
  begin
    WriteLn('Rectangle field:     ', ARectangle.Field():0:2);
    WriteLn('Rectangle perimeter: ', ARectangle.Perimeter():0:2);
  end;

  procedure InitConsole();
  begin
    TextColor(White);
    TextBackground(Blue);

    ClrScr();
  end;

var
  Rectangle : TRectangle;
begin
  InitConsole();

  LoadRectangleData(Rectangle);
  ShowRectangleData(Rectangle);

  ReadLn();
end.

Obiekt prostokąta zawiera w sobie tylko dane jego dotyczące oraz logikę (metody) określające inne jego właściwości, które nie są przechowywane w jego polach (czyli obliczające pole i obwód).

Natomiast wczytywanie danych i ich wyświetlanie jest temu obiektowi do niczego niepotrzebne – może spokojnie żyć bez tych metod. Dlatego są one zaimplementowane poza nim, jako zwykłe procedury, które wykonują konkretne czynności na podstawie lub dla obiektu dostarczonego w parametrze.

0

Dziękuję bardzo. Faktycznie czytelniej to wygląda i wydaje się logiczniejsze.
Czyli na obiekcie powinny być zawsze wykonywane konkretne obliczenia, a wszelkie wprowadzenia danych itd. poza nim?

1

Wprowadzanie danych czy ich wyświetlanie zawsze powinno być zrealizowane poza obiektem – ten należy jedynie takiej metodzie przekazać. Natomiast dany obiekt (a także rekord czy klasa) powinien zawsze zawierać tylko te dane, które są mu potrzebne do funkcjonowania.

Prostokątowui do istnienia potrzebne są jedynie jego wymiary, ew. położenie czy takie własności jak pole i obwód. Je wszystkie możesz zgrupować w polach, jednak te z reguły tworzy się prywatne, a do odczytu z nich wartości oraz modyfikacji korzysta się z właściwości, które określają poziom dostępu oraz pozwalają przy okazji wykonać czynności poboczne (np. automatycznie obliczyć pole i obwód po zmianie długości jednego z boków).

Do właściwości chyba jeszcze nie doszedłeś, więc na razie tyle powinno wystarczyć.

0

Jeszcze nie doszedłem :) Dziękuję ślicznie.
Niedługo pewnie jeszcze wrócę jak już bardzo będę pod ścianą

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