C产品如何满足特定用户需求?
- 内容介绍
- 文章标签
- 相关推荐
本文共计926个文字,预计阅读时间需要4分钟。
这是最常见的语法错误之一。例如,你写了这样的代码:
原因很简单:abstract 方法本身没实现体(连 {} 都不能有),它只负责“画接口”,强制子类补全。语言设计上不允许这种“半成品”存在于可实例化的类里。
- 抽象类可以包含普通方法、虚方法、抽象方法,甚至字段和属性
- 但只要类里有一个
abstract成员,这个类就必须用abstract修饰 - 抽象类本身不能
new实例化,哪怕它所有方法都已实现(只要带abstract关键字就不行)
virtual方法必须带实现体,哪怕只是空大括号
virtual 的核心是「默认行为 + 可选覆盖」。它不是占位符,而是真实可用的方法。所以 public virtual void Log() { } 合法,public virtual void Log();(没大括号)会编译失败。
这点和 abstract 形成鲜明对比:一个强调“必须留给子类填”,一个强调“我先兜底,你爱改不改”。
- 虚方法可被子类
override,也可不重写——调用时自动走基类逻辑 - 如果子类写了同名方法但漏了
override,编译器不会报错,但运行时不会多态调用,容易埋下隐蔽 bug -
virtual不能和private、static、abstract、override共存
子类重写时,override 是强制语法,不是可选风格
不管是重写 abstract 还是 virtual,子类方法前都必须加 override。这不是约定,是编译器检查点。
漏掉 override 的典型后果:父类变量引用子类对象时,调用的仍是父类版本——表面看代码“长得像重写”,实际完全没生效。
- 签名必须严格一致:返回类型、方法名、参数个数与类型,一个都不能差
-
private或static方法无法被override(编译错误) - 如果父类方法是
sealed override,那这一层就彻底封死,孙子类不能再override
选择 abstract 还是 virtual,关键看设计意图
这不是语法能力问题,而是建模判断:你希望子类“必须实现”,还是“可以沿用默认”?
比如定义图形基类:CalculateArea() 用 abstract 更合理——圆、矩形、三角形算法完全不同,基类根本没法提供有意义的默认值;而 ToString() 就适合 virtual——基类可以返回类型名,子类按需补充坐标或尺寸信息。
- abstract:契约型设计,用于定义“什么必须做”
- virtual:扩展型设计,用于定义“什么可以改”
- 两者都能触发多态,但约束强度不同,误用会导致编译失败或运行时逻辑错位
最容易被忽略的是:abstract 类里可以混用 virtual 和 abstract 方法,而 virtual 方法所在的普通类一旦被密封(sealed),其 virtual 成员就失去被重写的可能——这和 abstract 的强制继承逻辑本质冲突,所以 sealed 类里不允许有 virtual 成员。
本文共计926个文字,预计阅读时间需要4分钟。
这是最常见的语法错误之一。例如,你写了这样的代码:
原因很简单:abstract 方法本身没实现体(连 {} 都不能有),它只负责“画接口”,强制子类补全。语言设计上不允许这种“半成品”存在于可实例化的类里。
- 抽象类可以包含普通方法、虚方法、抽象方法,甚至字段和属性
- 但只要类里有一个
abstract成员,这个类就必须用abstract修饰 - 抽象类本身不能
new实例化,哪怕它所有方法都已实现(只要带abstract关键字就不行)
virtual方法必须带实现体,哪怕只是空大括号
virtual 的核心是「默认行为 + 可选覆盖」。它不是占位符,而是真实可用的方法。所以 public virtual void Log() { } 合法,public virtual void Log();(没大括号)会编译失败。
这点和 abstract 形成鲜明对比:一个强调“必须留给子类填”,一个强调“我先兜底,你爱改不改”。
- 虚方法可被子类
override,也可不重写——调用时自动走基类逻辑 - 如果子类写了同名方法但漏了
override,编译器不会报错,但运行时不会多态调用,容易埋下隐蔽 bug -
virtual不能和private、static、abstract、override共存
子类重写时,override 是强制语法,不是可选风格
不管是重写 abstract 还是 virtual,子类方法前都必须加 override。这不是约定,是编译器检查点。
漏掉 override 的典型后果:父类变量引用子类对象时,调用的仍是父类版本——表面看代码“长得像重写”,实际完全没生效。
- 签名必须严格一致:返回类型、方法名、参数个数与类型,一个都不能差
-
private或static方法无法被override(编译错误) - 如果父类方法是
sealed override,那这一层就彻底封死,孙子类不能再override
选择 abstract 还是 virtual,关键看设计意图
这不是语法能力问题,而是建模判断:你希望子类“必须实现”,还是“可以沿用默认”?
比如定义图形基类:CalculateArea() 用 abstract 更合理——圆、矩形、三角形算法完全不同,基类根本没法提供有意义的默认值;而 ToString() 就适合 virtual——基类可以返回类型名,子类按需补充坐标或尺寸信息。
- abstract:契约型设计,用于定义“什么必须做”
- virtual:扩展型设计,用于定义“什么可以改”
- 两者都能触发多态,但约束强度不同,误用会导致编译失败或运行时逻辑错位
最容易被忽略的是:abstract 类里可以混用 virtual 和 abstract 方法,而 virtual 方法所在的普通类一旦被密封(sealed),其 virtual 成员就失去被重写的可能——这和 abstract 的强制继承逻辑本质冲突,所以 sealed 类里不允许有 virtual 成员。

