พื้นฐาน KeyPath
อ้างอิงคุณสมบัติในฐานะค่าแบบชั้นหนึ่ง
พื้นฐาน KeyPath เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
Key path คืออะไร
เส้นทางคีย์ คือค่าที่อธิบายเส้นทางไปยังคุณสมบัติโดยยังไม่ได้เข้าถึงคุณสมบัตินั้นจริง ๆ ลองนึกภาพว่าเป็นการอ้างอิงที่จัดเก็บและนำกลับมาใช้ใหม่ได้ ซึ่งระบุว่าเราต้องการคุณสมบัติ ใด โดยแยกจากอินสแตนซ์ ใด ที่เราอ่านคุณสมบัตินั้น
คุณเขียนเส้นทางคีย์ด้วยแบ็กสแลช ตามด้วยชื่อชนิดข้อมูล จุด และชื่อคุณสมบัติ Swift จะให้ค่า KeyPath แก่นิพจน์นี้ ซึ่งคุณสามารถส่งต่อได้เหมือนค่าอื่น ๆ
struct Person {
let name: String
let age: Int
}
let nameKeyPath = \Person.name
print(type(of: nameKeyPath))การอ่านค่า
หากต้องการอ่านคุณสมบัติผ่านเส้นทางคีย์ ให้ใช้ซับสคริปต์ [keyPath:] กับอินสแตนซ์ โดยใส่เส้นทางคีย์ไว้ภายในวงเล็บเหลี่ยม แล้ว Swift จะคืนค่าที่อยู่ ณ เส้นทางนั้น
วิธีนี้ทำงานขณะรันไทม์แทนการเขียนชื่อคุณสมบัติโดยตรง แต่ตอนนี้คุณสมบัติจะถูกเลือกด้วยข้อมูลแทนที่จะกำหนดตายตัวในโค้ด
struct Person {
let name: String
let age: Int
}
let alice = Person(name: "Alice", age: 30)
let path = \Person.name
print(alice[keyPath: path])ไวยากรณ์ของเส้นทางคีย์โดยละเอียด
รูปแบบทั่วไปคืออักขระหลีกแบ็กสแลช ตามด้วยชนิดข้อมูลราก จุด และชื่อคุณสมบัติ แบ็กสแลชจะบอก Swift ว่าคุณต้องการเส้นทางคีย์ ไม่ใช่ค่าของคุณสมบัติ
ชนิดข้อมูลรากคือชนิดข้อมูลที่เส้นทางเริ่มต้น ส่วนชนิดข้อมูลผลลัพธ์คือชนิดข้อมูลของคุณสมบัติสุดท้าย ดังนั้นเส้นทางจาก Person ไปยังคุณสมบัติ age จึงมี Person เป็นราก และมี Int เป็นชนิดของค่า
struct Person {
let name: String
let age: Int
}
let ageKeyPath: KeyPath<Person, Int> = \Person.age
let bob = Person(name: "Bob", age: 42)
print(bob[keyPath: ageKeyPath])การเชื่อมผ่านคุณสมบัติที่ซ้อนกัน
เส้นทางคีย์สามารถเจาะเข้าไปในค่าที่ซ้อนกันได้ หากคุณสมบัติหนึ่งเป็น struct คุณสามารถต่อเส้นทางด้วยจุดอีกตัวเพื่อไปยังคุณสมบัติที่อยู่ลึกลงไป
ห่วงโซ่ทั้งหมดนี้ยังคงเป็นค่าเส้นทางคีย์เพียงค่าเดียว โดยชนิดข้อมูลรากและชนิดข้อมูลผลลัพธ์จะสะท้อนจุดเริ่มต้นและจุดสิ้นสุดของห่วงโซ่
struct Address {
let city: String
}
struct Person {
let name: String
let address: Address
}
let cityPath = \Person.address.city
let carol = Person(name: "Carol", address: Address(city: "Oslo"))
print(carol[keyPath: cityPath])การจัดเก็บเส้นทางคีย์ในตัวแปร
เนื่องจากเส้นทางคีย์เป็นเพียงค่า คุณจึงสามารถจัดเก็บไว้ในตัวแปร ส่งคืนจากฟังก์ชัน หรือเก็บเป็นชุดของเส้นทางคีย์ได้ วิธีนี้ช่วยให้คุณตัดสินใจว่าจะอ่านคุณสมบัติใดขณะรันไทม์
ในที่นี้เราเลือกหนึ่งในเส้นทางคีย์ที่จัดเก็บไว้สองเส้นทางโดยอิงตามแฟล็ก
struct Person {
let name: String
let age: Int
}
let showAge = true
let chosen: PartialKeyPath<Person> = showAge ? \Person.age : \Person.name
let dave = Person(name: "Dave", age: 27)
print(dave[keyPath: chosen])PartialKeyPath และ AnyKeyPath
Swift มีชนิดข้อมูลเส้นทางคีย์อยู่กลุ่มหนึ่ง KeyPath<Root, Value> รู้ทั้งจุดเริ่มต้นและจุดสิ้นสุด PartialKeyPath<Root> รู้จุดเริ่มต้นแต่ลบข้อมูลชนิดของค่าออก ส่วน AnyKeyPath จะลบข้อมูลชนิดของทั้งสองฝั่ง
ยิ่งคุณเก็บข้อมูลชนิดไว้มากเท่าไร คอมไพเลอร์ก็ยิ่งตรวจสอบให้คุณได้มากขึ้นเท่านั้น ให้เลือกใช้รูปแบบบางส่วนหรือรูปแบบใดก็ได้เฉพาะเมื่อคุณจำเป็นต้องผสมเส้นทางที่มีชนิดค่าต่างกันจริง ๆ
struct Person {
let name: String
let age: Int
}
let paths: [PartialKeyPath<Person>] = [\.name, \.age]
let eve = Person(name: "Eve", age: 19)
for p in paths {
print(eve[keyPath: p])
}รูปแบบย่อภายในชนิดข้อมูลที่ทราบอยู่แล้ว
เมื่อบริบทระบุชนิดข้อมูลรากไว้อยู่แล้ว คุณสามารถละชื่อชนิดข้อมูลและเขียนเพียงแบ็กสแลช จุด และคุณสมบัติได้ คอมไพเลอร์จะอนุมานชนิดข้อมูลรากให้
รูปแบบย่อนี้ช่วยให้จุดเรียกใช้สั้นลง โดยเฉพาะภายในการดำเนินการกับคอลเลกชันที่ทราบชนิดข้อมูลของสมาชิกอย่างชัดเจน
struct Person {
let name: String
let age: Int
}
func value(of person: Person, at path: KeyPath<Person, Int>) -> Int {
person[keyPath: path]
}
let frank = Person(name: "Frank", age: 55)
print(value(of: frank, at: \.age))เส้นทางคีย์ในอาร์กิวเมนต์ของฟังก์ชัน
รูปแบบที่พบได้บ่อยคือฟังก์ชันแบบทั่วไปที่รับเส้นทางคีย์แล้วนำไปใช้กับหลายอินสแตนซ์ วิธีนี้แยกสิ่งที่คุณอ่านออกจากตรรกะที่ใช้ดำเนินการอ่าน
ในที่นี้ตัวช่วยแบบทั่วไปจะแยกคุณสมบัติใด ๆ ของชนิดข้อมูลใด ๆ ออกจากรายการบุคคล
struct Person {
let name: String
let age: Int
}
func extract<T>(_ people: [Person], _ path: KeyPath<Person, T>) -> [T] {
people.map { $0[keyPath: path] }
}
let people = [Person(name: "Ana", age: 21), Person(name: "Ben", age: 34)]
print(extract(people, \.name))
print(extract(people, \.age))เส้นทางคีย์และคุณสมบัติที่คำนวณ
เส้นทางคีย์แบบอ่านอย่างเดียวทำงานร่วมกับคุณสมบัติที่คำนวณได้เช่นกัน เส้นทางจะเก็บการคำนวณไว้ ดังนั้นการอ่านผ่านเส้นทางจะเรียกใช้ตัวเข้าถึงค่า
นั่นหมายความว่าเส้นทางคีย์ไม่ได้จำกัดอยู่แค่คุณสมบัติที่จัดเก็บไว้ คุณสมบัติใด ๆ ที่อ่านได้ก็ใช้ได้
struct Rectangle {
let width: Double
let height: Double
var area: Double { width * height }
}
let areaPath = \Rectangle.area
let r = Rectangle(width: 3, height: 4)
print(r[keyPath: areaPath])เส้นทางคีย์เอกลักษณ์
มีเส้นทางคีย์พิเศษที่อ้างถึงค่าทั้งหมดของตัวมันเอง เขียนด้วยแบ็กสแลชเดี่ยวตามด้วยจุดและ self การอ่านผ่านเส้นทางนี้จะคืนค่าอินสแตนซ์เดิมโดยไม่เปลี่ยนแปลง
วิธีนี้มีประโยชน์เมื่อ API ต้องการเส้นทางคีย์ แต่คุณต้องการใช้องค์ประกอบนั้นโดยตรง เช่น การเรียงลำดับตัวเลขตามค่าของตัวเลขเอง
let numbers = [3, 1, 2]
let identity = \Int.self
for n in numbers {
print(n[keyPath: identity])
}การเปรียบเทียบเส้นทางคีย์
เส้นทางคีย์รองรับ Hashable และ Equatable เส้นทางคีย์สองเส้นทางที่ชี้ไปยังคุณสมบัติเดียวกันของชนิดข้อมูลเดียวกันจะเท่ากัน คุณจึงจัดเก็บไว้ในเซตหรือใช้เป็นคีย์ของพจนานุกรมได้
วิธีนี้มีประโยชน์สำหรับการสร้างตารางที่จับคู่คุณสมบัติกับป้ายกำกับหรือตัวจัดรูปแบบ
struct Person {
let name: String
let age: Int
}
let labels: [PartialKeyPath<Person>: String] = [
\Person.name: "Full Name",
\Person.age: "Years Old"
]
print(labels[\Person.age] ?? "unknown")ตรวจความเข้าใจอย่างรวดเร็ว: การอ่านผ่านเส้นทางคีย์
ทดสอบความเข้าใจของคุณเกี่ยวกับการอ่านคุณสมบัติผ่านเส้นทางคีย์
ทบทวน: พื้นฐานของเส้นทางคีย์
คุณได้เรียนรู้พื้นฐานของเส้นทางคีย์แล้ว:
- เส้นทางคีย์เขียนด้วยแบ็กสแลช ชนิดข้อมูลราก จุด และชื่อคุณสมบัติ โดยใช้อธิบายคุณสมบัติโดยไม่ต้องอ่านค่าของคุณสมบัตินั้น
- อ่านค่าด้วยซับสคริปต์
[keyPath:]บนอินสแตนซ์ - เส้นทางสามารถเชื่อมต่อเข้าไปยังคุณสมบัติที่ซ้อนกันและชี้ไปยังคุณสมบัติที่คำนวณได้
KeyPath,PartialKeyPathและAnyKeyPathแลกความปลอดภัยด้านชนิดข้อมูลกับความยืดหยุ่น- เส้นทางคีย์เป็นค่า จึงจัดเก็บ ส่งต่อ เปรียบเทียบ และใช้เป็นคีย์ของพจนานุกรมได้
ถัดไป คุณจะใช้เส้นทางคีย์เพื่อทำให้การดำเนินการกับคอลเลกชันกระชับขึ้นอย่างมาก
struct Person {
let name: String
let age: Int
}
let path = \Person.age
let gina = Person(name: "Gina", age: 48)
print("Read via key path: \(gina[keyPath: path])")คำถามที่พบบ่อย
บทเรียน “พื้นฐาน KeyPath” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “พื้นฐาน KeyPath” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “พื้นฐาน KeyPath”
อ้างอิงคุณสมบัติในฐานะค่าแบบชั้นหนึ่ง คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “พื้นฐาน KeyPath” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม
ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ