- F# 基础教程
- F# - 首页
- F# - 概述
- F# - 环境搭建
- F# - 程序结构
- F# - 基本语法
- F# - 数据类型
- F# - 变量
- F# - 运算符
- F# - 决策
- F# - 循环
- F# - 函数
- F# - 字符串
- F# - 可选类型
- F# - 元组
- F# - 记录
- F# - 列表
- F# - 序列
- F# - 集合
- F# - 映射
- F# - 判别联合
- F# - 可变数据
- F# - 数组
- F# - 可变列表
- F# - 可变字典
- F# - 基本输入输出
- F# - 泛型
- F# - 委托
- F# - 枚举
- F# - 模式匹配
- F# - 异常处理
- F# - 类
- F# - 结构体
- F# - 运算符重载
- F# - 继承
- F# - 接口
- F# - 事件
- F# - 模块
- F# - 命名空间
F# - 继承
面向对象编程中最重要的概念之一是继承。继承允许我们根据另一个类来定义一个类,这使得创建和维护应用程序变得更容易。这也提供了重用代码功能和加快实现时间的机会。
在创建类时,程序员可以指定新类应该继承现有类的成员,而不是完全编写新的数据成员和成员函数。这个现有的类称为基类,新类称为派生类。
继承的概念实现了 IS-A 关系。例如,哺乳动物 IS A 动物,狗 IS-A 哺乳动物,因此狗 IS-A 动物,依此类推。
基类和子类
子类派生自已定义的基类。子类继承基类的成员,并拥有自己的成员。
子类使用inherit关键字定义,如下所示:
type MyDerived(...) = inherit MyBase(...)
在 F# 中,一个类最多只能有一个直接基类。如果未使用inherit关键字指定基类,则该类隐式地继承自 Object。
请注意:
基类的的方法和成员对派生类的用户可用,就像派生类的直接成员一样。
let 绑定和构造函数参数对类是私有的,因此无法从派生类访问。
关键字base指的是基类实例。它像 self 标识符一样使用。
示例
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 类的Greet方法可以在派生类中重写。以下示例演示了这一点:
示例
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 类。但是,需要 Student 或 Teacher 类。在这种情况下,可以将 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.