Generic — ang esensya ng mga generic na uri at parameter T

May-akda: IT Sectr Nai-publish: 2026-06-18 Oras ng pagbabasa: 10 min

Generic (generic na programming) — ay isang mekanismo ng Swift na nagpapahintulot sa pagsulat ng mga uri at function na may parametrisadong uri . Sa halip na duplicate ang code para sa Int, String at custom na mga istraktura, ang developer ay lumikha ng isang generic na solusyon na gumagana sa anumang uri, habang pinapanatili ang mahigpit na pag-type. Ang compiler ay nag-substitute ng konkretong uri sa oras ng paggamit, na ginagarantiyahan ang kaligtasan nang walang pagkawala ng pagganap. Ayon sa Swift Book, 2025, ang mga generic na parameter ay isa sa mga pangunahing kakayahan ng wika, na nasa pundasyon ng standard library at SwiftUI.

Mga Pangunahing Punto

  • Generic — mekanismo ng generic na programming na may mga parameter-uri
  • Mga Function na may generic na parameter ay gumagana sa anumang uri nang walang pag-duplicate ng code
  • Mga paghihigpit ng where ay naglilimita sa saklaw ng generic sa mga uri na nakakatugon sa mga kondisyon
  • Associated Types sa mga protocol ay nagpapahintulot sa mga protocol na maging generic
  • Compiler ay lumilikha ng espesyalisadong code para sa bawat konkretong uri

Ano ang Generic sa Swift?

Generic (generic na uri) — ay isang syntactic na konstruksyon ng Swift na nagpapahintulot sa pagsulat ng nababaluktot, magagamit muli na code na may parametrisasyon ng uri. Sa halip ng konkretong uri, isang placeholder ay isinusulat sa mga angle bracket — karaniwang , ngunit anumang pangalan ay maaaring gamitin. Ang Generic ay nasa pundasyon ng SwiftUI (View, some View), standard library (Array, Optional) at Combine.

Bakit kailangan ang Generic

Kung walang generic, kailangan isulat ang magkakahiwalay na function para sa bawat uri: swapInts, swapStrings, swapDates. Ang generic na function na swap ay pumapalit sa lahat ng tatlong variant na may isang deklarasyon. Ito ay nagbabawas ng pag-duplicate, nagpapataas ng pagiging nababasa, at nagpapababa ng posibilidad ng mga pagkakamali sa pagkopya ng code.

swift
func swapValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

var x = 10
var y = 20
swapValues(&x, &y)

Ang Swift compiler ay lumilikha ng espesyalisadong code para sa bawat konkretong paggamit ng generic. Ibig sabihin nito na ang generic na function na swapValues ay walang overhead kumpara sa manual na isinulat na function para sa Int. Hindi ginagamit ng Swift ang pagbura ng uri tulad ng Java — ang generic ay umiiral pareho sa compilation phase at sa runtime (kahit na maaaring espesyalisahin sila ng optimization).

Mga generic na function na may parameter T

Mga generic na function — ay mga function na tumatanggap ng isa o higit pang mga parameter-uri. Ang mga parameter-uri ay ipinapakita pagkatapos ng pangalan ng function sa mga angle bracket: . Maaari silang gamitin sa signature: uri ng argumento, uri ng ibinabalik, at sa loob ng katawan ng function.

Maramihang parameter-uri

Ang isang function ay maaaring magkaroon ng maramihang generic na parameter. Halimbawa, ang function na findKey ay tumatanggap ng dictionary na may mga key K at value V. Ang bawat parameter-uri ay natatangi at maaaring gamitin sa mga paghihigpit.

swift
func findKey<K: Hashable, V>(
    for value: V,
    in dictionary: [K: V]
) -> K? where V: Equatable {
    for (key, dictValue) in dictionary {
        if dictValue == value {
            return key
        }
    }
    return nil
}

Ang mga paghihigpit na K: Hashable at where V: Equatable ay ginagarantiyahan na ang findKey ay matawag lamang sa isang dictionary na ang mga key ay nahahash at ang mga value ay maihahambing. Ang mga ganitong paghihigpit ay hindi burukrasya, kundi pangangailangan: kung walang Hashable, hindi maindeks ang paghahanap sa pamamagitan ng key, kung walang Equatable, hindi maihahambing ang value sa dictValue.

Mga paghihigpit ng uri sa pamamagitan ng where

where — ay isang keyword ng Swift na nagpapataw ng karagdagang mga paghihigpit sa mga generic na parameter. Hindi tulad ng simpleng pagtukoy ng protocol sa mga angle bracket (), ang where ay nagpapahintulot sa pagpapahayag ng mas kumplikadong mga kondisyon: pagsunod sa maramihang mga protocol, ugnayan sa pagitan ng mga parameter-uri at pagpipino ng associated types.

Syntax ng where

Ang where clause ay isinusulat pagkatapos ng signature ng function o uri, bago ang pambukas na curly brace. Sa where maaaring tukuyin na T: Comparable & Hashable (sabay na dalawang protocol), o na T.U == Int (konkretisasyon ng associated type).

swift
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
}

extension Container where Item: Comparable {
    func isSorted() -> Bool {
        // Implementation available only if Item: Comparable
        return true
    }
}

Ang extension na may where ay nagdadagdag ng mga pamamaraan lamang para sa mga uri na nakakatugon sa kondisyon. Ang Container ay makakakuha ng pamamaraang isSorted, ngunit ang Container ay hindi, dahil ang Any ay hindi Comparable. Ito ay isang malakas na mekanismo ng kondisyonal na pag-andar.

Associated Types sa mga protocol

Associated Types (mga kaugnay na uri) — ay isang paraan upang gawing generic ang protocol nang hindi tinutukoy ang konkretong uri sa phase ng deklarasyon. Sa halip ng , ang protocol ay nagdedeklara ng associatedtype, na kung saan ay konkretisado sa implementasyon. Ito ay lalong mahalaga para sa mga koleksyon: ang protocol na Sequence ay hindi alam kung anong mga elemento ang lalamanin ng sequence.

Ugnayan ng associated types sa pamamagitan ng where

Sa tulong ng where, ang mga ugnayan ay maaaring itatag sa pagitan ng associated types ng iba't ibang mga protocol. Halimbawa, maaaring kailanganin na ang Item ng isang protocol ay tumugma sa Iterator.Element ng isa pa. Ito ay ginagarantiyahan ang pagiging tugma ng uri sa antas ng compilation.

swift
protocol StackProtocol {
    associatedtype Element
    mutating func push(_ item: Element)
    mutating func pop() -> Element?
}

struct IntStack: StackProtocol {
    typealias Element = Int
    private var items: [Int] = []
    
    mutating func push(_ item: Int) { items.append(item) }
    mutating func pop() -> Int? { items.popLast() }
}

Ang IntStack ay nagkokonkreto ng Element bilang Int, gamit ang typealias. Ang compiler ay nagsusuri kung ang lahat ng mga kinakailangan ng protocol ay natutugunan sa uri na ito. Kung walang associated types, kailangan isulat ang StackProtocol na may generic na protocol, ngunit ang Swift ay gumagamit ng associated types para sa pagkakapareho sa mga tulay ng Objective-C at mas mahusay na pagiging nababasa.

Generic sa mga extension at subscript

Mga generic na extension ay nagpapahintulot sa pagdaragdag ng mga pamamaraan sa generic na uri na may karagdagang mga paghihigpit. Ito ay pattern ng “kondisyonal na pagsunod”, kung saan ang uri ay nakakakuha ng pag-andar lamang sa ilalim ng tiyak na mga kondisyon. Ang mga subscript ay maaari ding maging generic.

Generic na subscript

Ang isang subscript ay maaaring maging generic: ito ay tumatanggap ng generic na mga parameter sa mga angle bracket. Ito ay kapaki-pakinabang para sa ligtas na pag-access sa mga koleksyon na may arbitraryong index, kung saan ang index ay maaaring maging iba't ibang uri.

swift
extension Array where Element: Numeric {
    func sum() -> Element {
        return reduce(0, +)
    }
}

extension Array {
    subscript<Indices: Sequence>(indices: Indices) -> [Element]
        where Indices.Element == Int {
        return indices.map { self[$0] }
    }
}

Ang ganitong konstruksyon ay nagbibigay ng malakas na komposisyon: ang pamamaraang sum ay lumilitaw lamang sa mga numerikong array, at ang subscript na may arbitraryong mga index ay gumagana sa anumang sequence ng integer na mga index. Ang compiler mismo ang namamahala sa visibility ng mga miyembrong ito batay sa mga kondisyon ng where.

Mga karaniwang pagkakamali sa pagtatrabaho sa mga generics

Mga pagkakamali sa paggamit ng generic ay madalas na nauugnay sa hindi tamang mga paghihigpit o pagtatangkang gamitin ang generic kung saan kailangan ang konkretong uri. Tingnan natin ang tatlong karaniwang senaryo na kinakaharap ng mga developer.

Labis na parametrisasyon

Ang pagdaragdag ng mga generic na parameter kung saan sapat na ang konkretong uri — ay isang anti-pattern. Kung ang isang function ay palaging gumagana sa String, hindi kailangang gawin itong . Ito ay nagpapakumplikado ng code nang walang pakinabang. Ang generic ay makatwiran kapag ang uri ay talagang nag-iiba, hindi para sa abstract na “flexibilidad sa hinaharap”.

Nawawalang paghihigpit ng where

Ang pagtawag ng pamamaraan sa isang generic na parameter nang hindi tinutukoy na ang pamamaraan ay umiiral — ay isang pagkakamali. ay hindi maaaring tumawag ng .count kung hindi tinukoy na ang T: Collection. Palaging magdagdag ng mga paghihigpit sa mga parameter-uri, kung hindi man ay tatanggihan ng compiler ang code.

swift
// ❌ Error: value has no count method
func countElements<T>(value: T) -> Int { value.count }

// ✅ Works: T: Collection guarantees count exists
func countElements<T: Collection>(value: T) -> Int { value.count }

Ang pagkakamali ay mauunawaan: ang generic ay maaaring maging anumang uri at hindi alam ng compiler kung ito ay may count. Ang paghihigpit na Collection ay lumulutas ng problema. Katulad para sa Equatable, Hashable, Numeric — palaging tukuyin ang protocol kung plano mong tumawag ng mga pamamaraan o operator sa generic na parameter.

Mga Madalas Itanong

Ano ang Generic sa Swift sa simpleng salita?

Generic — ay isang paraan ng pagsulat ng code na gumagana sa anumang uri, nang hindi nadu-duplicate ang parehong lohika para sa Int, String at iba pang uri. Sa halip ng konkretong uri, ginagamit ang placeholder , na pinalitan ng tunay na uri sa oras ng paggamit.

Paano naiiba ang Generic sa Any?

Generic ay nagpapanatili ng impormasyon tungkol sa konkretong uri sa compilation phase, na nagpapahintulot sa compiler na suriin ang mga uri at lumikha ng optimize na code. Any — ay pagbura ng uri: anumang halaga ay maaaring ipasa, ngunit ang uri ay nawawala at kinakailangan ang conversion (as?).

Paano limitahan ang Generic gamit ang protocol?

Gamitin ang syntax na T: SomeProtocol sa mga angle bracket o isang hiwalay na clause na where T: SomeProtocol. Ginagarantiyahan ng mga paghihigpit na ang generic na parameter ay sumusuporta sa tiyak na mga pamamaraan at pag-aari.

Ano ang Associated Type sa isang protocol?

Associated Type (associatedtype) — ay isang placeholder para sa uri sa loob ng protocol. Ang protocol ay hindi tumutukoy ng konkretong uri, kundi nagdedeklara ng associatedtype na konkretisado sa implementasyon: ang Array ay may Element, ang Dictionary — Key at Value.

Mas mabilis ba o mas mabagal ang Generic kaysa sa konkretong uri?

Ang Swift ay nagko-compile ng generic code sa espesyalisadong bersyon para sa bawat konkretong uri. Sa praktika, ang generic na function para sa Int ay hindi mas mabagal kaysa sa manual na isinulat na function para sa Int. Walang overhead para sa abstraction.

Buod

  • Generic — mekanismo ng generic na programming na may parameter-uri
  • Mga function at uri na may generic na parameter ay pumapalit sa maraming naka-duplicate na implementasyon
  • Mga paghihigpit ng where ay naglilimita sa saklaw ng generic sa kinakailangang kondisyon
  • Associated Types ay nagpapahintulot sa mga protocol na maging generic nang walang konkretisasyon sa phase ng deklarasyon
  • Mga extension na may where ay nagdadagdag ng pag-andar lamang kapag natugunan ang mga kondisyon
  • Compiler ay lumilikha ng espesyalisadong code — ang generic ay hindi nagdaragdag ng overhead
  • Labis na parametrisasyon — anti-pattern, gamitin ang generic lamang kapag ang uri ay talagang nag-iiba

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din