@dynamicMemberLookup
สร้างการเข้าถึงสมาชิกแบบไดนามิกที่ปลอดภัยด้านชนิด
@dynamicMemberLookup เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
การค้นหาสมาชิกแบบไดนามิกคืออะไร
แอตทริบิวต์ @dynamicMemberLookup ช่วยให้ชนิดข้อมูลตอบสนองต่อการเข้าถึงสมาชิกด้วยรูปแบบจุด แม้สมาชิกนั้นจะไม่ได้ประกาศเป็นคุณสมบัติจริง เมื่อคุณเขียน value.something Swift จะส่งต่อการเรียกไปยังซับสคริปต์พิเศษที่คุณกำหนด
วิธีนี้ทำให้ชนิดตัวห่อหุ้มใช้งานได้เป็นธรรมชาติ ขณะเดียวกันก็รวมจุดที่จัดการการเข้าถึงไว้ในที่เดียว
@dynamicMemberLookup
struct Settings {
private var storage: [String: String] = ["theme": "dark"]
subscript(dynamicMember key: String) -> String? {
storage[key]
}
}
let s = Settings()
print(s.theme ?? "none")ซับสคริปต์ที่จำเป็น
ชนิดข้อมูลที่ทำเครื่องหมายด้วย @dynamicMemberLookup ต้องใช้งาน subscript(dynamicMember:) เมื่อพารามิเตอร์เป็น String ชื่อสมาชิกที่คุณพิมพ์จะกลายเป็นสตริงนั้นขณะทำงาน
ดังนั้น config.timeout จะเรียกซับสคริปต์ด้วยคีย์ "timeout"
@dynamicMemberLookup
struct Config {
let values: [String: Int]
subscript(dynamicMember member: String) -> Int {
values[member] ?? 0
}
}
let config = Config(values: ["timeout": 30, "retries": 3])
print(config.timeout)
print(config.retries)การค้นหาด้วยสตริงไม่ปลอดภัยด้านชนิดข้อมูล
การค้นหาสมาชิกแบบไดนามิกที่ใช้สตริงมีความยืดหยุ่น แต่สูญเสียการตรวจสอบขณะคอมไพล์ หากคุณสะกดชื่อสมาชิกผิด โค้ดก็ยังคอมไพล์ได้ และคุณจะได้รับสิ่งที่ซับสคริปต์คืนค่าสำหรับคีย์ที่ไม่มีอยู่
ในตัวอย่างด้านล่าง สมาชิกที่ไม่รู้จักจะคืนค่าเริ่มต้นอย่างเงียบ ๆ แทนที่จะทำให้การสร้างโปรแกรมล้มเหลว
@dynamicMemberLookup
struct Config {
let values: [String: Int]
subscript(dynamicMember member: String) -> Int {
values[member] ?? -1
}
}
let config = Config(values: ["timeout": 30])
print(config.tmout)การค้นหาที่ปลอดภัยด้านชนิดข้อมูลด้วยคีย์พาธ
เพื่อความปลอดภัย คุณสามารถให้ซับสคริปต์รับ KeyPath แทนสตริงได้ คราวนี้คอมไพเลอร์จะตรวจสอบว่าสมาชิกนั้นมีอยู่ในชนิดข้อมูลที่ถูกห่อหุ้มหรือไม่ ทำให้กลับมาตรวจสอบได้อย่างครบถ้วนขณะยังส่งต่อการเข้าถึงอยู่
รูปแบบนี้เหมาะอย่างยิ่งกับชนิดตัวห่อหุ้มที่เก็บค่าซึ่งมีชนิดข้อมูลชัดเจน
struct User { let name: String; let age: Int }
@dynamicMemberLookup
struct Boxed {
let user: User
subscript<T>(dynamicMember path: KeyPath<User, T>) -> T {
user[keyPath: path]
}
}
let boxed = Boxed(user: User(name: "Ada", age: 36))
print(boxed.name)
print(boxed.age)เหตุใดรูปแบบคีย์พาธจึงปลอดภัยกว่า
เนื่องจากซับสคริปต์รับ KeyPath<User, T> จึงอนุญาตเฉพาะสมาชิกที่มีอยู่จริงใน User เท่านั้น การพิมพ์ผิดอย่าง boxed.naem จะทำให้คอมไพล์ไม่ผ่าน ต่างจากรูปแบบที่ใช้สตริง
คุณได้ความสะดวกของรูปแบบจุดโดยไม่มีความเสี่ยงดังกล่าว
struct User { let name: String; let age: Int }
@dynamicMemberLookup
struct ReadOnly {
let value: User
subscript<T>(dynamicMember path: KeyPath<User, T>) -> T {
value[keyPath: path]
}
}
let r = ReadOnly(value: User(name: "Lin", age: 22))
print(r.name, r.age)สมาชิกไดนามิกแบบเขียนได้
หากซับสคริปต์มีตัวกำหนดค่าและรับ WritableKeyPath คุณก็สามารถกำหนดค่าให้กับสมาชิกที่ส่งต่อได้ ตัวห่อหุ้มจะส่งต่อการเขียนไปยังค่าที่ถูกห่อหุ้มโดยตรง
วิธีนี้ทำให้ได้ตัวห่อหุ้มที่เปลี่ยนแปลงได้และทำงานอย่างโปร่งใส
struct Profile { var name: String; var score: Int }
@dynamicMemberLookup
struct Wrapper {
var value: Profile
subscript<T>(dynamicMember path: WritableKeyPath<Profile, T>) -> T {
get { value[keyPath: path] }
set { value[keyPath: path] = newValue }
}
}
var w = Wrapper(value: Profile(name: "Mo", score: 0))
w.score = 99
print(w.value.score)การส่งต่อไปยังอ็อบเจ็กต์ที่ถูกห่อหุ้ม
การค้นหาสมาชิกแบบไดนามิกเหมาะอย่างยิ่งกับพร็อกซีขนาดเล็กที่ส่งต่อไปยังค่าภายในเป็นส่วนใหญ่ แต่เพิ่มพฤติกรรมบางอย่าง ตัวซับสคริปต์ช่วยรวมตรรกะการส่งต่อไว้ในที่เดียว
ที่นี่ตัวห่อหุ้มสำหรับการบันทึกข้อมูลจะส่งต่อการ read และแสดงสมาชิกที่ถูกเข้าถึง
struct Account { let id: Int; let balance: Double }
@dynamicMemberLookup
struct Logged {
let account: Account
subscript<T>(dynamicMember path: KeyPath<Account, T>) -> T {
let result = account[keyPath: path]
print("accessed a member")
return result
}
}
let logged = Logged(account: Account(id: 7, balance: 100))
print(logged.balance)การทำงานร่วมกับแนวคิดการเรียกใช้งานแบบไดนามิก
การค้นหาสมาชิกแบบไดนามิกทำงานร่วมกับชนิดข้อมูลทั่วไปได้ดี ซับสคริปต์ทั่วไปเพียงรายการเดียวสามารถส่งต่อคุณสมบัติที่มีชนิดใดก็ได้ ดังนั้นตัวห่อหุ้มหนึ่งตัวจึงใช้กับค่าที่มีรูปแบบหลากหลายได้
ที่นี่ Proxy เดียวกันใช้ได้ไม่ว่าสมาชิกนั้นจะเป็นสตริงหรือจำนวนเต็ม
struct Item { let title: String; let count: Int }
@dynamicMemberLookup
struct Proxy<Wrapped> {
let wrapped: Wrapped
subscript<T>(dynamicMember path: KeyPath<Wrapped, T>) -> T {
wrapped[keyPath: path]
}
}
let proxy = Proxy(wrapped: Item(title: "Book", count: 4))
print(proxy.title, proxy.count)การค้นหาด้วยสตริงสำหรับข้อมูลลักษณะ JSON
รูปแบบที่ใช้สตริงยังมีประโยชน์สำหรับการแทนข้อมูลที่มีโครงสร้างไม่ตายตัว เช่น JSON ที่แยกวิเคราะห์แล้ว ซึ่งไม่ทราบสมาชิกขณะคอมไพล์ การเข้าถึงแต่ละครั้งจะกลายเป็นการค้นหาในพจนานุกรม
ที่นี่ค่าขนาดเล็กที่มีลักษณะเหมือน JSON จะเปิดเผย fields ผ่านรูปแบบจุด
@dynamicMemberLookup
struct JSON {
let fields: [String: String]
subscript(dynamicMember key: String) -> String {
fields[key] ?? ""
}
}
let json = JSON(fields: ["city": "Oslo", "country": "Norway"])
print(json.city)
print(json.country)ข้อจำกัดที่ควรคำนึงถึง
การค้นหาสมาชิกแบบไดนามิกมีผลเฉพาะไวยากรณ์การเข้าถึงสมาชิกเท่านั้น ไม่ได้เพิ่มคุณสมบัติที่จัดเก็บจริง เครื่องมืออย่างการเติมโค้ดอัตโนมัติทำงานกับรูปแบบคีย์พาธได้ แต่ไม่ทำงานกับคีย์สตริงที่กำหนดขึ้นเอง
ควรเลือกรูปแบบคีย์พาธเมื่อโครงสร้างพื้นฐานเป็นที่รู้จัก และสงวนรูปแบบสตริงไว้สำหรับข้อมูลที่เป็นไดนามิกอย่างแท้จริง
struct Point { let x: Int; let y: Int }
@dynamicMemberLookup
struct Safe {
let point: Point
subscript<T>(dynamicMember path: KeyPath<Point, T>) -> T {
point[keyPath: path]
}
}
let safe = Safe(point: Point(x: 3, y: 4))
print(safe.x + safe.y)ตัวตกแต่งที่ใช้งานได้จริง
เมื่อนำแนวคิดทั้งหมดมารวมกัน ต่อไปนี้คือตัวห่อหุ้มที่เก็บสถิติ โดยส่งต่อการ read คุณสมบัติทุกครั้งไปยังค่าภายในพร้อมนับจำนวนการเข้าถึง กรอบงานจริงใช้แนวคิดนี้สำหรับการเฝ้าสังเกตและการติดตาม
รูปแบบจุดบนตัวห่อหุ้มให้ความรู้สึกเหมือนกับการใช้ value โดยตรงทุกประการ
struct Sensor { let temperature: Double; let humidity: Double }
@dynamicMemberLookup
class Tracked {
let sensor: Sensor
var reads = 0
init(_ s: Sensor) { sensor = s }
subscript<T>(dynamicMember path: KeyPath<Sensor, T>) -> T {
reads += 1
return sensor[keyPath: path]
}
}
let t = Tracked(Sensor(temperature: 21.5, humidity: 0.4))
print(t.temperature)
print(t.humidity)
print(t.reads)ตรวจสอบด่วน: การค้นหาแบบไดนามิกที่ปลอดภัยด้านชนิดข้อมูล
ลองนึกดูว่าพารามิเตอร์ของซับสคริปต์ใดทำให้การค้นหาสมาชิกแบบไดนามิกปลอดภัยด้านชนิดข้อมูล
สรุป: การค้นหาสมาชิกแบบไดนามิก
คุณได้เรียนรู้การทำงานของ @dynamicMemberLookup แล้ว:
- แอตทริบิวต์นี้จะส่งต่อการเข้าถึงด้วยไวยากรณ์จุดที่ไม่ได้ประกาศไปยัง
subscript(dynamicMember:) - พารามิเตอร์
Stringช่วยให้เข้าถึงข้อมูลได้อย่างยืดหยุ่นแต่ไม่มีการตรวจสอบชนิด เหมาะสำหรับข้อมูลรูปแบบคล้ายเจสัน - พารามิเตอร์
KeyPathช่วยให้กลับมามีความปลอดภัยด้านชนิดข้อมูลอย่างสมบูรณ์และใช้การเติมโค้ดอัตโนมัติได้ WritableKeyPathที่มีตัวตั้งค่าช่วยให้คุณส่งต่อการเขียนผ่านตัวห่อหุ้มได้- นี่เป็นความสะดวกด้านไวยากรณ์ที่เข้าคู่กับรูปแบบพร็อกซีและเดคอเรเตอร์ได้อย่างเป็นธรรมชาติ
ตอนนี้คุณมีชุดเครื่องมือเส้นทางคีย์ครบถ้วนแล้ว ทั้งการอ่าน การเขียน การใช้งานกับคอลเลกชัน และการส่งต่อแบบไดนามิก
struct User { let name: String }
@dynamicMemberLookup
struct Wrap {
let user: User
subscript<T>(dynamicMember path: KeyPath<User, T>) -> T {
user[keyPath: path]
}
}
print(Wrap(user: User(name: "Final")).name)เรียนรู้ Swift ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 122
- บทเรียน
- 409
คำถามที่พบบ่อย
บทเรียน “@dynamicMemberLookup” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “@dynamicMemberLookup” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “@dynamicMemberLookup”
สร้างการเข้าถึงสมาชิกแบบไดนามิกที่ปลอดภัยด้านชนิด คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “@dynamicMemberLookup” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม
ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐาน KeyPath
- การใช้ KeyPaths ในคอลเลกชัน
- KeyPath ที่เขียนได้และอ้างอิงได้
- @dynamicMemberLookup