F # - การถ่ายทอดทางพันธุกรรม
แนวคิดที่สำคัญที่สุดอย่างหนึ่งในการเขียนโปรแกรมเชิงวัตถุคือการสืบทอด การสืบทอดช่วยให้เรากำหนดคลาสในรูปแบบของคลาสอื่นซึ่งทำให้ง่ายต่อการสร้างและดูแลแอปพลิเคชัน นอกจากนี้ยังให้โอกาสในการนำฟังก์ชันโค้ดกลับมาใช้ซ้ำและใช้งานได้รวดเร็ว
เมื่อสร้างคลาสแทนที่จะเขียนสมาชิกข้อมูลและฟังก์ชันสมาชิกใหม่ทั้งหมดโปรแกรมเมอร์สามารถกำหนดได้ว่าคลาสใหม่ควรสืบทอดสมาชิกของคลาสที่มีอยู่ คลาสที่มีอยู่นี้เรียกว่าคลาสพื้นฐานและคลาสใหม่เรียกว่าคลาสที่ได้รับ
แนวคิดเรื่องการถ่ายทอดทางพันธุกรรมดำเนินความสัมพันธ์ IS-A ตัวอย่างเช่นสัตว์เลี้ยงลูกด้วยนมเป็นสัตว์สุนัข IS-A สัตว์เลี้ยงลูกด้วยนมดังนั้นสุนัข IS-A เช่นกันและอื่น ๆ
คลาสพื้นฐานและคลาสย่อย
คลาสย่อยมาจากคลาสฐานซึ่งกำหนดไว้แล้ว คลาสย่อยจะสืบทอดสมาชิกของคลาสพื้นฐานและมีสมาชิกของตัวเอง
คลาสย่อยถูกกำหนดโดยใช้ inherit คีย์เวิร์ดตามรูปด้านล่าง -
type MyDerived(...) =
inherit MyBase(...)
ใน F # คลาสสามารถมีคลาสพื้นฐานโดยตรงได้สูงสุดหนึ่งคลาส หากคุณไม่ได้ระบุคลาสพื้นฐานโดยใช้inherit คีย์เวิร์ดคลาสโดยปริยายสืบทอดมาจาก Object
โปรดทราบ -
เมธอดและสมาชิกของคลาสพื้นฐานพร้อมใช้งานสำหรับผู้ใช้คลาสที่ได้รับเช่นสมาชิกโดยตรงของคลาสที่ได้รับ
อนุญาตให้การผูกและพารามิเตอร์ตัวสร้างเป็นไพรเวตของคลาสดังนั้นจึงไม่สามารถเข้าถึงได้จากคลาสที่ได้รับ
คำหลัก baseหมายถึงอินสแตนซ์คลาสพื้นฐาน ใช้เหมือนตัวระบุตัวเอง
ตัวอย่าง
type Person(name) =
member x.Name = name
member x.Greet() = printfn "Hi, I'm %s" x.Name
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
p.Greet()
st.Greet()
tr.Greet()
เมื่อคุณคอมไพล์และรันโปรแกรมจะให้ผลลัพธ์ดังต่อไปนี้ -
Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam
วิธีการลบล้าง
คุณสามารถแทนที่พฤติกรรมเริ่มต้นของเมธอดคลาสพื้นฐานและนำไปใช้งานที่แตกต่างกันในคลาสย่อยหรือคลาสที่ได้รับ
วิธีการใน F # ไม่สามารถเขียนทับได้โดยค่าเริ่มต้น
ในการแทนที่เมธอดในคลาสที่ได้รับคุณต้องประกาศเมธอดของคุณว่าสามารถเขียนทับได้โดยใช้ abstract และ default คีย์เวิร์ดดังนี้ -
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
ตอนนี้วิธีการทักทายของคลาส Person สามารถถูกแทนที่ในคลาสที่ได้รับ ตัวอย่างต่อไปนี้แสดงให้เห็นถึงสิ่งนี้ -
ตัวอย่าง
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
override x.Greet() = printfn "Student %s" x.Name
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
override x.Greet() = printfn "Teacher %s." x.Name
//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
//default Greet
p.Greet()
//Overriden Greet
st.Greet()
tr.Greet()
เมื่อคุณคอมไพล์และรันโปรแกรมจะให้ผลลัพธ์ดังต่อไปนี้ -
Hi, I'm Mohan
Student Zara
Teacher Mariam.
คลาสนามธรรม
ในบางครั้งคุณจำเป็นต้องจัดเตรียมการใช้งานวัตถุที่ไม่สมบูรณ์ซึ่งไม่ควรนำมาใช้ในความเป็นจริง ต่อมาโปรแกรมเมอร์คนอื่น ๆ ควรสร้างคลาสย่อยของคลาสนามธรรมเพื่อการใช้งานที่สมบูรณ์
ตัวอย่างเช่นชั้นบุคคลจะไม่จำเป็นในระบบการจัดการโรงเรียน อย่างไรก็ตามจำเป็นต้องใช้นักเรียนหรือชั้นครู ในกรณีเช่นนี้คุณสามารถประกาศคลาส Person เป็นคลาสนามธรรมได้
AbstractClass แอตทริบิวต์บอกคอมไพเลอร์ว่าคลาสมีสมาชิกนามธรรมบางส่วน
คุณไม่สามารถสร้างอินสแตนซ์ของคลาสนามธรรมได้เนื่องจากคลาสไม่ได้ถูกนำไปใช้อย่างสมบูรณ์
ตัวอย่างต่อไปนี้แสดงให้เห็นถึงสิ่งนี้ -
ตัวอย่าง
[<AbstractClass>]
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
override x.Greet() = printfn "Student %s" x.Name
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
override x.Greet() = printfn "Teacher %s." x.Name
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
//Overriden Greet
st.Greet()
tr.Greet()
เมื่อคุณคอมไพล์และรันโปรแกรมจะให้ผลลัพธ์ดังต่อไปนี้ -
Student Zara
Teacher Mariam.