0Pricing
Swift Academy · บทเรียน

ชนิดดำรงอยู่ด้วย any และการลบชนิด

ใช้ any Protocol ทำความเข้าใจต้นทุนด้านประสิทธิภาพ และทราบว่าเมื่อใดควรเลือกชนิดทั่วไป

ชนิดดำรงอยู่ด้วย any และการลบชนิด เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

ประเภทอัตถิภาวะคืออะไร

ประเภทอัตถิภาวะจะบรรจุค่าใดก็ได้ที่สอดคล้องกับโพรโทคอลไว้เบื้องหลังอินเทอร์เฟซแบบเดียวกัน โดยแก้ไขการทำงานขณะรันไทม์

protocol Drawable { func draw() }
struct Line: Drawable { func draw() { print("Line") } }
let d: any Drawable = Line()
d.draw()

คีย์เวิร์ด any

Swift 5.7 กำหนดให้ใช้คีย์เวิร์ด any ก่อนชื่อโพรโทคอลที่ใช้เป็นประเภทอัตถิภาวะ เพื่อให้การบรรจุค่ามีความชัดเจน

func render(_ shape: any Drawable) {
  shape.draw()
}
render(Line())

ต้นทุนของประเภทอัตถิภาวะ

ประเภทอัตถิภาวะใช้การจัดสรรหน่วยความจำบนฮีพและการเรียกแบบไดนามิก ซึ่งอาจช้ากว่า generic ที่ใช้การเรียกแบบคงที่

// Existential – dynamic dispatch, potential heap alloc
var shapes: [any Drawable] = [Line(), Line()]
// Generic – static dispatch, no boxing
func drawGeneric<T: Drawable>(_ s: T) { s.draw() }

ปัญหาของ PAT และประเภทอัตถิภาวะ

โพรโทคอลที่มีชนิดที่เกี่ยวข้องไม่สามารถใช้เป็นชนิดอัตถิภาวะโดยตรงได้ หากไม่มีการลบชนิดข้อมูล

protocol Container { associatedtype Item }
// var c: any Container // Swift 5.7 allows with "any" but loses Item info

รูปแบบการลบชนิดข้อมูล

ตัวห่อหุ้มที่ลบชนิดข้อมูลจะห่อชนิดข้อมูลรูปธรรมไว้ภายในโครงสร้าง โดยซ่อนชนิดข้อมูลรูปธรรมดังกล่าว

struct AnyDrawable: Drawable {
  private let _draw: () -> Void
  init<D: Drawable>(_ d: D) { _draw = d.draw }
  func draw() { _draw() }
}

AnySequence และ AnyPublisher

ไลบรารีมาตรฐานของ Swift และ Combine มีตัวห่อหุ้มที่ลบชนิดข้อมูล เช่น AnySequence และ AnyPublisher

import Combine
let subject = PassthroughSubject<Int, Never>()
let pub: AnyPublisher<Int, Never> = subject.eraseToAnyPublisher()

eraseToAnyPublisher()

eraseToAnyPublisher() ซ่อนสายผู้เผยแพร่ข้อมูลรูปธรรม ทำให้โค้ดที่เรียกใช้พึ่งพาเฉพาะ AnyPublisher

func fetch() -> AnyPublisher<String, Error> {
  URLSession.shared.dataTaskPublisher(for: URL(string: "https://example.com")!)
    .map { String(data: $0.data, encoding: .utf8) ?? "" }
    .eraseToAnyPublisher()
}

เมื่อใดจึงควรใช้ชนิดอัตถิภาวะ

ใช้ชนิดอัตถิภาวะกับคอลเลกชันที่มีสมาชิกต่างชนิดกัน หรือเมื่อไม่ทราบชนิดข้อมูลที่แน่นอนขณะคอมไพล์

var widgets: [any Drawable] = [] // mixed concrete types OK

เลือกใช้เจเนอริกแทนชนิดอัตถิภาวะ

เมื่อทำได้ ให้แทนที่ชนิดอัตถิภาวะด้วยเจเนอริก เพื่อให้ได้การเรียกใช้แบบสแตติกและประสิทธิภาพที่ดีขึ้น

// Prefer this:
func draw<T: Drawable>(_ item: T) { item.draw() }
// Over this:
func draw(_ item: any Drawable) { item.draw() }

การเปิดชนิดอัตถิภาวะ

Swift 5.7 ขึ้นไปสามารถเปิดชนิดอัตถิภาวะเมื่อเรียกใช้ฟังก์ชันเจเนอริก โดยแยกชนิดข้อมูลพื้นฐานออกมาโดยอัตโนมัติ

func drawGeneric<T: Drawable>(_ d: T) { d.draw() }
let d: any Drawable = Line()
drawGeneric(d) // compiler opens the existential automatically

การลบชนิดข้อมูลเทียบกับชนิดข้อมูลทึบ

การลบชนิดข้อมูลจะซ่อนชนิดข้อมูลเพื่อให้ใช้งานกับข้อมูลต่างชนิดกันได้ ส่วนชนิดข้อมูลทึบจะคงเอกลักษณ์ของชนิดข้อมูลไว้สำหรับชนิดผลลัพธ์เดียวที่สอดคล้องกัน

let erased: any Drawable = Line()   // runtime type unknown
let opaque: some Drawable = Line()   // compile-time fixed type

ตรวจสอบความเข้าใจ

ต้นทุนด้านประสิทธิภาพหลักของชนิดอัตถิภาวะคืออะไร

ทบทวนบทเรียน

ชนิดอัตถิภาวะ (any Protocol) ทำให้เกิดพหุรูปแบบขณะทำงาน โดยมีต้นทุนเป็นการเรียกใช้แบบไดนามิก การลบชนิดข้อมูลจะห่อชนิดข้อมูลรูปธรรมไว้เบื้องหลังอินเทอร์เฟซที่เสถียร ควรเลือกใช้เจเนอริกเพื่อประสิทธิภาพ และใช้ชนิดอัตถิภาวะกับคอลเลกชันที่มีสมาชิกต่างชนิดกัน

คำถามที่พบบ่อย

บทเรียน “ชนิดดำรงอยู่ด้วย any และการลบชนิด” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ชนิดดำรงอยู่ด้วย any และการลบชนิด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ชนิดดำรงอยู่ด้วย any และการลบชนิด”

ใช้ any Protocol ทำความเข้าใจต้นทุนด้านประสิทธิภาพ และทราบว่าเมื่อใดควรเลือกชนิดทั่วไป คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ชนิดดำรงอยู่ด้วย any และการลบชนิด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม

ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ข้อจำกัดของชนิดทั่วไปและส่วนคำสั่ง where
  2. ชนิดทึบแสงด้วยคีย์เวิร์ด some
  3. ชนิดดำรงอยู่ด้วย any และการลบชนิด
  4. ชนิดที่เชื่อมโยงหลักและการโยนข้อผิดพลาดที่มีชนิด
← กลับไปที่ Swift Academy