Klasy i obiekty w C# — podstawy OOP

Klasy i obiekty
1 Klasy
Definicja Klasy:
- Klasa w języku C# to szablon lub plan, na podstawie którego tworzone są obiekty. Reprezentuje abstrakcję pewnego rodzaju jednostki w systemie.
- Klasy są fundamentem programowania obiektowego, pozwalają na strukturyzację i organizację kodu.
- Klasa definiuje cechy (pola), zachowanie (metody) oraz funkcjonalności obiektu.
Struktura Klasy:
- Pola (Prywatne Dane): Pola przechowują dane charakteryzujące obiekt klasy. Są to zmienne, które należą do konkretnej instancji klasy.
- Właściwości: Właściwości pozwalają na kontrolowany dostęp do pól klasy i umożliwiają walidację danych przed zapisem lub odczytem.
- Metody (Funkcje): Metody to funkcje, które mogą operować na polach klasy i wykonywać różne operacje. Metody definiują zachowania obiektu.
- Konstruktory: Konstruktor to specjalna metoda wywoływana podczas tworzenia nowej instancji klasy. Służy do inicjalizacji obiektu.
- Indeksery: Indeksery pozwalają na dostęp do elementów obiektu za pomocą indeksu, podobnie jak w przypadku tablic. Wartość indeksu może być dowolnym typem, a nie tylko typem liczbowym.
- Zdarzenia: Zdarzenia umożliwiają subskrypcję i obsługę zdarzeń wywoływanych w klasie.
- Statyczność: Członkowie statyczni (metody, pola) należą do klasy, a nie do konkretnej instancji. Są dostępne bez konieczności tworzenia obiektu danej klasy.
przykład
public class Narzedzie
{
public static int LiczbaNarzedzi;
}
Definicja Klasy przykład
public class Samochod
{
// Członkowie klasy (pola, właściwości, metody)
}
Pola (Fields) i Właściwości (Properties)
public class Samochod
{
public string Marka; // Pole
private int _rokProdukcji; // Pole prywatne
public int RokProdukcji // Właściwość
{
get { return _rokProdukcji; }
set { _rokProdukcji = value > 1900 ? value : 1900; }
}
}
Metody
public class Samochod
{
public void UruchomSilnik()
{
// Logika uruchamiania silnika
}
public int ObliczWiekSamochodu()
{
return DateTime.Now.Year - RokProdukcji;
}
}
Konstruktory
public class Samochod
{
public Samochod(string marka, int rokProdukcji)
{
Marka = marka;
RokProdukcji = rokProdukcji;
}
}
Indeksery
using System;
public class Biblioteka
{
private string[] ksiazki = new string[10];
// Indekser
public string this[int indeks]
{
get
{
if (indeks >= 0 && indeks < ksiazki.Length)
{
return ksiazki[indeks];
}
else
{
return "Indeks poza zakresem";
}
}
set
{
if (indeks >= 0 && indeks < ksiazki.Length)
{
ksiazki[indeks] = value;
}
else
{
Console.WriteLine("Indeks poza zakresem");
}
}
}
}
class Program
{
static void Main()
{
Biblioteka mojaBiblioteka = new Biblioteka();
// Ustawienie wartości za pomocą indeksera
mojaBiblioteka[0] = "Asp.Net Core";
mojaBiblioteka[1] = "Csharp";
mojaBiblioteka[2] = "Xml";
// Pobranie wartości za pomocą indeksera
Console.WriteLine(mojaBiblioteka[1]); // Wyświetli: Asp.Net Core
Console.WriteLine(mojaBiblioteka[5]); // Wyświetli: Indeks poza zakresem
}
}
Zdarzenia
using System;
// Klasa reprezentująca nadawcę zdarzenia
public class Nadawca
{
// Definicja delegata zdarzenia
public delegate void MojDelegat(string wiadomosc);
// Zdarzenie oparte na delegacie
public event MojDelegat MojEvent;
// Metoda, która wywołuje zdarzenie
public void WywolajZdarzenie(string wiadomosc)
{
Console.WriteLine("Nadawca: Wysyłam wiadomość - " + wiadomosc);
// Sprawdzamy, czy zdarzenie ma zarejestrowane jakieś obszary nasłuchujące
if (MojEvent != null)
{
// Wywołujemy zdarzenie, przekazując wiadomość
MojEvent(wiadomosc);
}
}
}
// Klasa reprezentująca odbiorcę zdarzenia
public class Odbiorca
{
// Metoda obsługująca zdarzenie
public void ObslugaZdarzenia(string wiadomosc)
{
Console.WriteLine("Odbiorca: Otrzymałem wiadomość - " + wiadomosc);
}
}
class Program
{
static void Main()
{
// Tworzymy obiekty nadawcy i odbiorcy
Nadawca mojNadawca = new Nadawca();
Odbiorca mojOdbiorca = new Odbiorca();
// Rejestrujemy metodę ObslugaZdarzenia jako obszar nasłuchujący zdarzenia w nadawcy
mojNadawca.MojEvent += mojOdbiorca.ObslugaZdarzenia;
// Wywołujemy zdarzenie
mojNadawca.WywolajZdarzenie("Nowa wiadomość!");
}
}
Oczekiwany wynik:
Nadawca: Wysyłam wiadomość - Nowa wiadomość!
Odbiorca: Otrzymałem wiadomość - Nowa wiadomość!
2 Obiekty
Definicja
- Obiekt to konkretna instancja klasy.
- Możemy utworzyć wiele obiektów na podstawie jednej klasy.
- Każdy obiekt ma swoje unikalne atrybuty (wartości pól) i może wywoływać metody klasy.
- Tworzenie obiektu polega na alokowaniu pamięci i inicjalizowaniu jego pól i właściwości zgodnie z definicją klasy.
- Obiekty są niezależne i mogą mieć różne stany.
Tworzenie Obiektu:
- new – obiekt jest tworzony za pomocą operatora
newwraz z wywołaniem konstruktora klasy.
Przykład:Samochod mojSamochod = new Samochod("Toyota", "Camry", 2022); - Referencje: Obiekty są przekazywane przez referencje. Oznacza to, że przypisanie jednego obiektu do innego nie tworzy nowego obiektu, ale kopiuje referencję do tego samego obiektu w pamięci.
Dostęp do Członków Klasy:
- Pola i metody klasy mogą być dostępne z poziomu obiektu, a dostęp do nich odbywa się za pomocą operatora
.. - Przykład:
mojSamochod.PokazInformacje();
Osoba osoba1 = new Osoba("Jan", "Kowalski");
Osoba osoba2 = new Osoba("Anna", "Nowak");
osoba1.PrzedstawSie(); // "Jestem Jan Kowalski."
osoba2.PrzedstawSie(); // "Jestem Anna Nowak."
3 Filary Programowania obiektowego
Encapsulation (Enkapsulacja):
Enkapsulacja to zasada programowania obiektowego, która polega na ukrywaniu wewnętrznych detali implementacyjnych klasy i ujawnianiu tylko potrzebnych interfejsów.
Dostęp do pól i metod jest kontrolowany przez mechanizmy takie jak modyfikatory dostępu ( public, private, protected, internal, protected internal) które określają, które elementy klasy są widoczne dla innych części kodu. Co pomaga w zabezpieczaniu i izolowaniu wewnętrznych szczegółów implementacji.
Enkapsulacja pomaga w utrzymaniu spójności danych i umożliwia łatwiejsze utrzymanie kodu, ponieważ zmiany w implementacji mogą być ukrywane przed innymi częściami programu.
public class Samochod
{
// private - dostęp tylko w obrębie klasy
private int _rokProdukcji;
// public - dostęp z dowolnego miejsca
public int RokProdukcji
{
get { return _rokProdukcji; }
set { _rokProdukcji = value > 1900 ? value : 1900; }
}
}
Dziedziczenie
Dziedziczenie to mechanizm, który pozwala na tworzenie nowych klas na podstawie istniejących klas. Dziedziczenie umożliwia jednej klasie (klasie pochodnej) korzystanie z cech i zachowań innej klasy (klasy bazowej). Dziedziczenie pozwala na ponowne wykorzystanie kodu i tworzenie hierarchii klas, co ułatwia organizację kodu i wprowadzanie zmian w jednym miejscu.
public class Zwierze
{
public void Oddychaj()
{
Console.WriteLine("Zwierze oddycha.");
}
}
public class Ptak : Zwierze
{
public void Lataj()
{
Console.WriteLine("Ptak lata.");
}
}
Ptak dziedziczy metodę Oddychaj od klasy Zwierze.
Polimorfizm
Polimorfizm to koncepcja, która pozwala na traktowanie różnych obiektów w jednolity sposób. Możesz używać obiektów klas pochodnych jako obiektów klas bazowych.
Polimorfizm umożliwia jednemu interfejsowi obsługiwać różne typy obiektów lub jednej metodzie obsługiwać różne formy danych. W C#, polimorfizm może być osiągnięty poprzez przeciążanie metod, przesłanianie metod, interfejsy i klasy abstrakcyjne.
Metody wirtualne i abstrakcyjne umożliwiają nadpisywanie funkcji w klasach pochodnych.
public class Kształt
{
public virtual void Narysuj()
{
Console.WriteLine("Rysuję kształt.");
}
}
public class Kwadrat : Kształt
{
public override void Narysuj()
{
Console.WriteLine("Rysuję kwadrat.");
}
}
public class Kolo : Kształt
{
public override void Narysuj()
{
Console.WriteLine("Rysuję koło.");
}
}
Korzystając z polimorfizmu, możemy używać wspólnego interfejsu (Kształt) do obsługi różnych konkretnych implementacji (Kwadrat, Kolo).
Abstrakcja
Abstrakcja polega na ukrywaniu zbędnych detali implementacyjnych i skupianiu się na istotnych aspektach danego obiektu. Jest to proces tworzenia modelu, który koncentruje się na najważniejszych cechach i zachowaniach, ignorując mniej istotne szczegóły.
Klasy Abstrakcyjne:
Klasy abstrakcyjne są klasami, które nie mogą być instancjonowane bezpośrednio, ale mogą zawierać metody abstrakcyjne, czyli metody, które nie posiadają implementacji w klasie abstrakcyjnej. Klasy te służą jako szablony do dziedziczenia.
public abstract class Figura
{
public abstract double PolePowierzchni(); // Metoda abstrakcyjna
}
Interfejsy:
Interfejsy to zbiorcze zestawy metod, które są implementowane przez różne klasy. W odróżnieniu od klas abstrakcyjnych, interfejsy nie zawierają żadnej implementacji i umożliwiają implementację wielu interfejsów w jednej klasie.
public interface IDzwieki
{
void WydajDzwiek();
}
Właściwości Abstrakcyjne:
Właściwości abstrakcyjne pozwalają na definiowanie abstrakcyjnych pól w klasach abstrakcyjnych. Implementacja tych pól zostanie dostarczona przez klasę dziedziczącą.
public abstract class Pojazd
{
public abstract string Marka { get; set; }
}
Abstrakcja pozwala na tworzenie bardziej ogólnych i elastycznych struktur w kodzie, co z kolei ułatwia rozbudowę i modyfikację systemu. Jest to kluczowa koncepcja w programowaniu obiektowym, która pomaga w modelowaniu rzeczywistych problemów i skupianiu się na istotnych aspektach systemu.
Filary programowania obiektowego stanowią podstawę dla wielu zaawansowanych koncepcji i technik w programowaniu. Wspierają one tworzenie kodu, który jest bardziej elastyczny, łatwiejszy do zrozumienia, utrzymania i rozbudowy. Programowanie obiektowe jest kluczowym paradygmatem programowania, który jest szeroko stosowany we współczesnym oprogramowaniu.
Chcesz zobaczyć te same idee w praktyce? Zobacz 4 filary programowania obiektowego w C# i Interfejsy w C# — czysty kod bez powtórzeń.
Jeśli wolisz zacząć od prostszego, bardziej przystępnego wprowadzenia z analogią do klocków LEGO zamiast suchej teorii, sprawdź Obiekty w C# to jak Klocki LEGO — dobry punkt startowy przed tym artykułem.
🚀 Co dalej?
Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.
- 🗺️ Pobierz darmową roadmapę Junior .NET Developer — 12 kroków od podstaw C# do pierwszej pracy: dev-hobby.pl
- 🎬 Subskrybuj kanał YouTube — nowe filmy co tydzień.
9 comments
Dodaj komentarz
Musisz się zalogować, aby móc dodać komentarz.
Zamień wiedzę w umiejętności
Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.
Pobieram roadmapę →
Całość jest dobrze zorganizowana i prezentuje kluczowe koncepcje programowania obiektowego w C#.
Przykłady są zrozumiałe, a komentarze dodają wartości, wyjaśniając koncepcje i podając przykłady zastosowań.
Klarowne przedstawienie filarów programowania obiektowego, a także wartościowa lista dodatkowych tematów do zrozumienia.
Dodatkowe tematy, takie jak Klasy i Metody Statyczne, Metody Generyczne, czy Metody Rozszerzeń, są dobrze ujęte.
Dobrze wytłumaczona koncepcja abstrakcji i różnice między klasami abstrakcyjnymi a interfejsami.
Przykłady klas abstrakcyjnych i interfejsów są zrozumiałe.
asne wyjaśnienie, co to jest obiekt i jak tworzyć instancje klas.
Przekazanie informacji o referencjach w kontekście przypisywania obiektu do innego obiektu jest pomocne.
Przykład z zdarzeniem jest świetny, pokazuje jak działa mechanizm subskrypcji i obsługi zdarzeń w C#.
Dobrze, że zwrócono uwagę na sprawdzenie, czy zdarzenie ma zarejestrowane obszary nasłuchujące przed jego wywołaniem.
Wyjaśnienie pól i właściwości jest zrozumiałe. Dobrze pokazane różnice między publicznymi polami a prywatnymi polami z właściwościami.
Właściwość RokProdukcji zastosowująca walidację to dobry sposób na kontrolę danych.