Sobes.tech
Junior

Jaka jest podobieństwo i różnica między zwykłą a abstrakcyjną klasą?

sobes.tech AI

Odpowiedź od AI

W Golang nie ma pojęcia "zwykłej klasy" i "klasy abstrakcyjnej" w formie, w jakiej istnieją one w językach obiektowych typu Java czy C#.

Jednakże, ich funkcjonalność można imitować, używając struktur i interfejsów.

Podobieństwa (używając struktur i interfejsów w Golang):

  • Stan (dane): Struktura może zawierać pola, podobnie jak zwykła klasa przechowująca właściwości.
  • Zachowanie (metody): Do struktury można dołączać metody, które będą określać jej zachowanie, podobnie jak metody zwykłej klasy.
  • Wspólny kontrakt (dla klasy abstrakcyjnej i interfejsu): Interfejs w Golang definiuje zestaw metod, które musi zaimplementować każda struktura "implementująca" ten interfejs. To przypomina to, jak klasa abstrakcyjna lub interfejs w innych językach określa kontrakt dla dziedziczących lub implementujących klasy.

Różnice (w kontekście Golang):

Cecha "Zwykła klasa" (struktura z metodami) "Klasa abstrakcyjna" (interfejs + struktury)
Tworzenie bezpośrednie Można utworzyć instancję struktury. Nie można utworzyć instancji interfejsu.
Implementacja metod Wszystkie metody dołączone do struktury mają implementację. Interfejs tylko deklaruje metody, ale nie ich implementację.
Dziedziczenie Nie ma dziedziczenia w klasycznym sensie. Można używać kompozycji (wstawianie struktur). Interfejs nie dziedziczy, ale jest implementowany przez struktury.
Obowiązkowość implementacji Nie ma obowiązku implementowania określonego zestawu metod, oprócz tych dołączonych do struktury. Każda struktura, która "implementuje" interfejs Golang, musi dostarczyć implementację wszystkich jego metod.
Przechowywanie stanu (pól) Struktura może zawierać pola danych. Interfejs nie zawiera pól danych.

Przykład imitacji:

// interfejs imitujący klasę abstrakcyjną
type Shape interface {
	Area() float64
	Perimeter() float64
}

// struktura imitująca zwykłą klasę
type Circle struct {
	Radius float64
}

// implementacja metod interfejsu dla Circle
func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
	return 2 * 3.14 * c.Radius
}

// Inna struktura implementująca interfejs
type Rectangle struct {
	Width, Height float64
}

func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
	return 2 * (r.Width + r.Height)
}

W tym przykładzie Shape działa jako kontrakt (podobny do klasy abstrakcyjnej lub interfejsu w innych językach), a Circle i Rectangle to konkretne implementacje (odpowiedniki zwykłych klas). Możemy tworzyć instancje Circle i Rectangle, ale nie możemy bezpośrednio tworzyć instancji Shape. Obie struktury muszą również implementować metody Area() i Perimeter(), aby "spełniać" interfejs Shape.