Menu
Coddy logo textTech

Łańcuchowe wywoływanie metod

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 81 z 107.

Łączenie metod to technika, w której metody zwracają odbiorcę, umożliwiając łączenie wielu wywołań metod w jednym poleceniu. Wzorzec Builder już wykorzystuje tę technikę, ale jest to samodzielna koncepcja przydatna w wielu kontekstach.

Kluczem jest zwracanie wskaźnika do struktury z każdej metody:

type Query struct {
    table   string
    columns []string
    where   string
    limit   int
}

func (q *Query) Select(cols ...string) *Query {
    q.columns = cols
    return q
}

func (q *Query) From(table string) *Query {
    q.table = table
    return q
}

func (q *Query) Where(condition string) *Query {
    q.where = condition
    return q
}

func (q *Query) Limit(n int) *Query {
    q.limit = n
    return q
}

Teraz możesz płynnie łączyć te wywołania:

query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)

W porównaniu z osobnymi instrukcjami ten zapis przypomina niemal język naturalny. Łańcuchowe wywoływanie metod sprawdza się najlepiej, gdy operacje konfigurują lub modyfikują obiekt i nie muszą zwracać innych wartości. Jest powszechnie stosowane w kreatorach zapytań, interfejsach API do konfiguracji i bibliotekach asercji testowych.

Pamiętaj, że każda metoda musi używać odbiornika wskaźnikowego i zwracać *StructType, aby łańcuch działał prawidłowo.

challenge icon

Wyzwanie

Łatwy

Zbudujmy elastyczny kreator elementów HTML, który wykorzystuje łączenie metod do tworzenia tagów HTML z atrybutami i treścią! To praktyczne zastosowanie łączenia metod: utworzysz API, które podczas budowania elementów HTML będzie niemal przypominać język naturalny.

Podzielisz kod na dwa pliki:

  • element.go: Zdefiniuj kreator elementów HTML za pomocą metod, które można łączyć.

    Utwórz strukturę Element, która przechowuje nazwę tagu, mapę atrybutów (ciąg znaków na ciąg znaków) oraz wewnętrzną treść. Zbuduj metody, które można łączyć i z których każda zwraca *Element:

    • NewElement(tag string) - konstruktor tworzący nowy element z podaną nazwą tagu i zainicjalizowaną (pustą) mapą atrybutów
    • Attr(key, value string) - dodaje atrybut do elementu
    • ID(id string) - metoda pomocnicza ustawiająca atrybut "id"
    • Class(class string) - metoda pomocnicza ustawiająca atrybut "class"
    • Content(text string) - ustawia wewnętrzną treść elementu

    Dodaj metodę Render(), która zwraca ciąg znaków HTML. Atrybuty powinny być ułożone alfabetycznie według klucza. Format:

    <tag attr1="value1" attr2="value2">content</tag>

    Jeśli nie ma atrybutów, po prostu wyrenderuj <tag>content</tag>. Jeśli nie ma treści, wyrenderuj <tag attr="value"></tag>.

  • main.go: Buduj elementy HTML, łącząc metody.

    Wczytaj nazwę tagu, a następnie liczbę operacji do wykonania. Każda operacja to jeden z elementów:

    • id, po którym następuje wartość ID
    • class, po którym następuje wartość klasy
    • attr, po którym następuje nazwa i wartość atrybutu (dwa wiersze)
    • content, po którym następuje tekst treści

    Połącz wszystkie operacje w jeden płynny łańcuch metod, a następnie wyświetl wyrenderowany kod HTML.

Podane zostaną następujące dane wejściowe:

  • Wiersz 1: Nazwa tagu
  • Wiersz 2: Liczba operacji
  • Kolejne wiersze: Typ operacji i wartość lub wartości

Na przykład dla danych:

div
3
id
container
class
main-content
content
Hello World

Wynik powinien wyglądać tak:

<div class="main-content" id="container">Hello World</div>

A dla danych:

a
3
attr
href
https://example.com
attr
target
_blank
content
Click here

Wynik powinien wyglądać tak:

<a href="https://example.com" target="_blank">Click here</a>

A dla danych:

input
2
attr
type
text
attr
placeholder
Enter name

Wynik powinien wyglądać tak:

<input placeholder="Enter name" type="text"></input>

A dla danych:

p
1
content
Simple paragraph

Wynik powinien wyglądać tak:

<p>Simple paragraph</p>

Zwróć uwagę, jak łączenie metod pozwala budować elementy krok po kroku w czytelny sposób. Każda metoda modyfikuje element i zwraca go, co pozwala bezpośrednio łączyć kolejne wywołania metod.

Spróbuj swoich sił

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// Wczytaj nazwę tagu
	scanner.Scan()
	tagName := scanner.Text()

	// Wczytaj liczbę operacji
	scanner.Scan()
	numOps, _ := strconv.Atoi(scanner.Text())

	// Utwórz element
	element := NewElement(tagName)

	// Przetwórz każdą operację
	for i := 0; i < numOps; i++ {
		scanner.Scan()
		operation := scanner.Text()

		// TODO: W zależności od typu operacji wywołaj odpowiednią metodę w łańcuchu
		// Możliwe operacje: "id", "class", "attr" lub "content"
		// - Dla "id": wczytaj następny wiersz jako wartość ID
		// - Dla "class": wczytaj następny wiersz jako wartość klasy
		// - Dla "attr": wczytaj następne DWA wiersze (nazwę atrybutu, a potem jego wartość)
		// - Dla "content": wczytaj następny wiersz jako treść
		// Użyj łańcuchowego wywoływania metod, aby płynnie zbudować element

		_ = operation // Usuń ten wiersz podczas implementacji
	}

	// Wypisz wyrenderowany HTML
	fmt.Println(element.Render())
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online