Metody skrócenie kodu?

0

Cześć. To są moje początki programowania w C# i właśnie próbuję ogarnąć klasy i metody.
Dla testu napisałem programik do liczenia obwodu i pola prostokąta.
Powiem tak: program działa ale nie da się uprościć tego kodu?

namespace ConsoleApp4
{
    class prostokat
    {
        public int Pole(int a, int b)
        {
            int wynik = a * b;
            return wynik;   
        }

        public int Obwod(int a, int b)
        {
            int wynik =2*a+2*b;
            return wynik;

        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            int a=Int16.Parse(Console.ReadLine());
            int b=Int16.Parse(Console.ReadLine());
            int wynik1;
            int wynik2;
            prostokat obwod = new prostokat();
            wynik1=obwod.Obwod(a,b);
            prostokat pole=new prostokat();
            wynik2=pole.Pole(a,b);
            Console.WriteLine("pole {0} obwód{1}", wynik2, wynik1);
        }
    }
}

Chodzi mi głównie o to czy mogę w metodzie użyć zmiennych a i b zadeklarowanych w klasie prostokat? Czy tak się nie da?
Bo mam wrażenie, że do tego mini programu deklaruję masę niepotrzebnych zmiennych. Oczywiście mógłbym to zrobić bez METOD ale jak napisałem na początku bardziej chodzi mi o napisanie czegoś żebym zrozumiał sens.

prostokat obwod = new prostokat();
            wynik1=obwod.Obwod(a,b);

Czy tego zapisu też nie można jakoś uprościć?
Kiedyś uczyłem się Pascala i tam można było napisać funkcje.Jeśli dobrze zrozumiałem sens METOD to można założyć że metody w C# to prawie to samo co funkcje/procedury w Pascalu?

4
prostokat obwod = new prostokat();
wynik1=obwod.Obwod(a,b);
prostokat pole=new prostokat();
wynik2=pole.Pole(a,b);

Dlaczego tak? Nie musisz 2 razy wywoływać tego.
Można prościej. BTW: Klasy piszemy z wielkiej litery

var prostokat = new Prostokat();
var obwod = prostokat.Obwod(a,b);
var pole = prostokat.Pole(a,b);

Możesz również użyć konstruktora klasy, do której przekażesz zmienne a i b

class Prostokat
    {
        private int _a;
        private int _b;
    
        public Prostokat(int a, int b){
          _a = a;
          _b = b;
        }
        public int Pole()
        {
            return _a * _b;   
        }

        public int Obwod()
        {
            return 2*_a+2*_b;
        }
    }

Wywołujesz to tak:

var prostokat = new Prostokat(a,b);
var obwod = prostokat.Obwod();
var pole = prostokat.Pole();

Możesz również wykorzystać właściwości:

class Prostokat
    {
        public int ZmiennaA {get;set;}
        public int ZmiennaB {get;set;}
    
        public int Pole()
        {
            return _zmiennaA * _zmiennaB;   
        }

        public int Obwod()
        {
            return 2*_zmiennaA+2*_zmiennaB;
        }
    }
var prostokat = new Prostokat(){ _zmiennaA = a, _zmiennaB = b};
var obwod = prostokat.Obwod();
var pole = prostokat.Pole();

Jeszcze możesz wykorzystać metody/klasy statyczne.

Edit: Wykorzystałem tutaj słowo kluczowe var, aby jawnie nie deklarować typu(przyzwyczajenie). Nie musisz również wcześniej tworzyć zmiennej

int obwod;
obwod = prostokat.Obwod();

tylko wystarczy

var obwod = prostokat.Obwod();

Edit2: Jeżeli gdzieś wkradł się babol to przepraszam, miałem iść właśnie spać :)

4
Michalk001 napisał(a):

Możesz również wykorzystać właściwości:

class Prostokat
    {
        public int ZmiennaA {get;set;}
        public int ZmiennaB {get;set;}
    
        public int Pole()
        {
            return _zmiennaA * _zmiennaB;   
        }

        public int Obwod()
        {
            return 2*_zmiennaA+2*_zmiennaB;
        }
    }

Można jeszcze skrócić implementację metod, eliminując return:

        public int Pole() => _zmiennaA * _zmiennaB;
        public int Obwod() => 2 * _zmiennaA + 2 * _zmiennaB;
2

@specjal1990:

"Krótkość" kodu nie jest jedynym kryterium jego jakości.
Póki co, to jest anty-obiektowy choć niby ma klasy itd...
Nazwy są brzydkie, niezgodne ze zwyczajami. Klasy C# zaczynamy z wielkiej lkitery

Dyskusja o skróceniu kodu, który jest niskiej jakości, jest sztuczna. najpierw by tzreba dwybrac, w jakim paradygmacie to chesz zrobić. Obecnie robisz w czymś nie wiadomo co.

Do użycia nie-obiektowego, tak jak jest teraz, metody powinny być statyczne i wołane prostokąt.Obwod(a,b) czy ulepszone o wielką literę Prostokąt.Obwod(a,b), a samej klasy nie alokujemy przez new. Taka nie obiektowa, proceduralna klasa, to brzydka klasa, a właściwie nią w sensie OOP nie jest.

Do obiektowego Prostokat p = new Prostokat(a,b); a potem p.Obwod();

0

Domyślam się że te nazwy są źle napisane. Po prostu w nocy to pisałem i bardziej zależało mi poznać logikę METOD. A właściwie co robi to NEW w moim kodzie? Bo z przykładów które analizowałem na potrzeby nauki zrozumiałem tyle że to po prostu musi tam być. Tak jak pisałem pierwsze kroki stawiałem w pascalu i tam bym po prostu zdefiniował funkcję PROSTOKAT

funkcja prostokat(a, b)
{rób cos ze zmiennymi a i b}
A w ciele programu po prostu ją wywołuje np
prostokat(20,30)

I to mi się wydaje dużo mniej zawiłe. Bo w C# mam wrażenie że dużo dłuższy kod jest do tego potrzebny. Być może źle zrozumiałem sens METOD?

0

@specjal1990: W takich przykładowych prostych programikach to nawet prostackie skrypty w Pythonie (bez klas) mają "przyjemniejszy" kod...

Ale jak siądziesz do kodu aplikacji, który ma tysiące linijek w wielu plikach, to zobaczysz, że jednak jest lepiej gdy ten kod jest uporządkowany w klasach z metodami.

A właściwie co robi to NEW w moim kodzie?

new wywołuje konstruktor klasy i jest potrzebny, żeby w ogóle utworzyć instancję tej klasy (obiekt typu Prostokat).
Dzięki temu aplikacja rezerwuje pamięć na obiekt dopiero w czasie wykonywania, a nie przy uruchamianiu aplikacji.

W Pascalu też tak można robić. Tyle że jest to bardziej niskopoziomowa operacja: https://pl.wikibooks.org/wiki/Object_Pascal/Typy_zmiennych#Typ_wska%C5%BAnikowy

0

No właśnie rozumiem że przez to kod ma być bardziej przejrzysty i zrozumiały. Po prostu na przykładzie tego mini programu chciałem zobaczyć działanie metod. I miałem wrażenie że coś bardzo źle robie. Bo o ile samo napisanie metody uważam za spoko to już jej użycie później wydawało mi się trochę skomplikowane.

Console.WriteLine(prostokat.Pole(10,20));

Czy w taki bardzo skrócony sposób nie dałoby się wypisać pola na ekranie? Bez pisania dodatkowych zmiennych wynik? Może zły kurs czytam i ma ktoś lepsze wyjaśnienie metod i klas?

3

Jeśli nie potrzebujesz przechowywać wymiarów prostokąta, to proszę bardzo...
Napisz sobie statyczną klasę, która ma metody...

public static class Prostokat
{
    public static int Pole(int a, int b)
    {
        return a * b;   
    }
    public static int Obwod(int a, int b)
    {
        return 2 * a + 2 * b;
    }
}

Wtedy będziesz mógł napisać po prostu:

Console.WriteLine(Prostokat.Pole(10,20));

Bez tworzenia obiektów itd.

Ale jeśli będziesz chciał nanieść sobie te prostokąty na układ współrzędnych i np. sprawdzać czy jeden nachodzi na drugi, to lepiej mieć dwa obiekty typu prostokąt i napisać metodę, która sprawdza czy prostokąt podany jako argument metody, koliduje z prostokątem na rzecz, którego wywołujemy tą metodę:

    public bool Kolizja(Prostokat p)
    {
        // sprawdzanie kolizji z Prostokatem p
    }

Oczywiście trzeba będzie dodać jakieś pola do klasy, które np. będą nam mówić jaką pozycję ma prostokąt, jakie ma wymiary i pod jakim kątem jest obrócony.
Można by to załatwić jedną długą statyczną metodą, która ma 6+ argumentów - właściwości jednego prostokąta i właściwości drugiego prostokąta. Ale chyba przyznasz, że to mało obiektowe rozwiązanie :] I lepiej operować na obiektach typu Prostokat.

0

Ok dzięki teraz chyba zostało mi już to wyjaśnione we właściwy sposób.

0
specjal1990 napisał(a):

Domyślam się że te nazwy są źle napisane. Po prostu w nocy to pisałem i bardziej zależało mi poznać logikę METOD. A właściwie co robi to NEW w moim kodzie? Bo z przykładów które analizowałem na potrzeby nauki zrozumiałem tyle że to po prostu musi tam być. Tak jak pisałem pierwsze kroki stawiałem w pascalu i tam bym po prostu zdefiniował funkcję PROSTOKAT

funkcja prostokat(a, b)
{rób cos ze zmiennymi a i b}
A w ciele programu po prostu ją wywołuje np
prostokat(20,30)

I to mi się wydaje dużo mniej zawiłe.

  1. najbliższym odpowiednikiem funkcji jest statyczna metoda - słusznie @Spine podniósł, że w statycznej klasie (to taka form,a deklaracji klasy w C#, ze nie ma żadnym elementów "instancyjnych" czyli obiektowych (instancyjny, czyli zwiazany z jedną sztuką tej klasy), dla takiej klasy nie da się zawołac new)

  2. Nazwa. to i w funkcjach nadal ważne. Nazwa prostokąt(a,b) nie jest dobrą nazwą, już lepszą (oblicz_)pole_prostokąta(a,b) (w stylu klasycznego C) lub (Oblicz)PoleProstokata(a,b) w stylu C#
    Oblicz w nawiasie podaję jako przykład jak myśleć, na takim etapie myśl o funkcji jako o czasowniku (choć dopuszczam skrót w pisowni)

    W językach, która grupują nazwy w pewnych przestrzeniach w szerokim sensie, a w klasach statycznych C# w wąskim, pojawia się taka dogodna rzecz jak nazwa kwalifikowana, wtedy prostokąt ląduje przed kropką, a czynność szczegółowa za kropką Prostokąt.ObliczPole(a,b) (potem tego "Prostokąt" można się pozbyć, ale nie wszystko na raz, dopiero zaczynasz)

    Bo w C# mam wrażenie że dużo dłuższy kod jest do tego potrzebny. Być może źle zrozumiałem sens METOD?

Nie jest dłuższy w żadnym istotnym sensie. Doprowadzenie do jakiejś organizacji funkcji/metod w grupy/przestrzenie jest bardzo pozytywną rzeczą, więc dwa wiersze mieć to warto. tego nie czujesz, jak masz jedną/ dwie funkcje / metody, ale przy pół tysiącu funkcji PHP w jednej płaskiej przestrzenie, to dobre nie jest.

0

Żebym dobrze zrozumiał sens tej całej obiektowości to czy dla tego konkretnego programu warto w ogóle tworzyć klasę? Czy lepiej po prostu dodać samą metodę do głównego ciała programu? Zakładamy, że potrzebuję tylko pole i obwód wyliczony na podstawie zmiennych wpisanych przez użytkownika. Chodzi mi o to co jest bardziej poprawne "programistycznie"? Osobna klasa Prostokat z dwiema metodami Obwod i Pole czy po prostu dwie metody bez nowej klasy?

0
specjal1990 napisał(a):

Żebym dobrze zrozumiał sens tej całej obiektowości to czy dla tego konkretnego programu warto w ogóle tworzyć klasę? Czy lepiej po prostu dodać samą metodę do głównego ciała programu? Zakładamy, że potrzebuję tylko pole i obwód wyliczony na podstawie zmiennych wpisanych przez użytkownika. Chodzi mi o to co jest bardziej poprawne "programistycznie"? Osobna klasa Prostokat z dwiema metodami Obwod i Pole czy po prostu dwie metody bez nowej klasy?

Nie da się obiektowości wyłożyć w jednym poście, zwłaszcza ze jesteśmy na etapie mocno początkowym. Bez książki się nie da.

Poniewaz w C# (w Javie tak samo) nie może być funkcji poza klasą (jak w pascalu), wiec w tych jezyukach jest to element obowiazkowy. I tak być miał klase Main(), ale bardzo rasopwe jest klasa Prostokąt. Hipotycznie klasę Prostokąt mozesz wykorzystac jeszcze raz w innym projekcie, klasy Main raczej nie.

Zostańmy na tym etapie na statycznych, nie da się w powietrzu, bez fundamentów, wyłożyć OOP.

1
specjal1990 napisał(a):

Żebym dobrze zrozumiał sens tej całej obiektowości to czy dla tego konkretnego programu warto w ogóle tworzyć klasę? Czy lepiej po prostu dodać samą metodę do głównego ciała programu? Zakładamy, że potrzebuję tylko pole i obwód wyliczony na podstawie zmiennych wpisanych przez użytkownika. Chodzi mi o to co jest bardziej poprawne "programistycznie"? Osobna klasa Prostokat z dwiema metodami Obwod i Pole czy po prostu dwie metody bez nowej klasy?

Jeśli piszesz kodzik, który ma Ci na szybko policzyć konkretną rzecz, to nie ma co się wysilać.
Przecież nie będziesz go potem nigdzie publikował, ani go używał.
Ale po to są języki skryptowe typu Python. Żeby jeszcze mniej się wysilać.

Jeśli jednak robisz programik na zaliczenie na studia, to powinieneś pokazać jakoś, że ogarniasz te obiekty.
Żeby się tego nauczyć, robi się proste aplikacje, a nie od razu zaawansowane, w których Ci się wszystko pomiesza.

Poczytaj sobie jakąś książkę, np. https://helion.pl/ksiazki/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm
Może przykładowe kody autora jakoś do Ciebie przemówią. Pokażą Ci jak myśleć i jak to wygląda w codziennej pracy...

1
specjal1990 napisał(a):

Żebym dobrze zrozumiał sens tej całej obiektowości

Tu nie zmagasz się w ogóle z obiektowością. Problem jest w pisaniu w stylu "proceduralnym" w języku obiektowym, a skoro język ma takie przeznacenie, są tego pewne niewielkie "koszty"

W prawdziwym programowaniu obiektowym, na poziomie maksymalnie uproszczonym, możesz myśleć o obiekcie jako o rzeczy, która ma jakieś atrybuty, indywidualność, jest odróznialna od innej tego samego typuy (klasy), a metody to czynnosci.

var mojPies = new Pies("Burek");
mojPies.Szczeka();

W najmniejszym stopniu nie chce CIę tego tu i teraz uczyć, raczej machnąć ręką w kier północnym "tam jest niebieski szlak"

3
ZrobieDobrze napisał(a):

Poniewaz w C# (w Javie tak samo) nie może być funkcji poza klasą (jak w pascalu), wiec w tych jezyukach jest to element obowiazkowy.

Już nie.

void foo()
{
    System.Console.WriteLine("Hello, World!");
}

foo();
2

@Azarien

To nadal jest w klasie, różnica polega na implicit vs explicit.

Top-level statements to po prostu "dużo haków" :D

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.DisableOptimizations)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[CompilerGenerated]
internal class Program
{
    private static void <Main>$(string[] args)
    {
        <<Main>$>g__foo|0_0();
    }

    [CompilerGenerated]
    internal static void <<Main>$>g__foo|0_0()
    {
        Console.WriteLine("Hello, World!");
    }
}
0

Mogę jeszcze dorzucić jedno pytanie w tym wątku? Używam Visual Studio 2022 i czasami gdy chcę edytować kod w środku linijki to VS zamiast dodawać litery do danej linijki to je zastępuje. Wtedy zamiast ustawić kursor np miedzy 7 a 8 znakiem i coś tam wpisac muszę usunąć wszystko do 7 znaku i całą resztę dopisać. Jak wyłączę i włącze VS to już mogę normalnie edytować. Czy jakiś skrót uruchamia taki tryb edycji? Mam nadzieję że jest zrozumiałe o co mi chodzi.

5

Naciśnij klawisz INSERT na klawiaturze.

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