若一个实例方法的声明中含有 virtual 修饰符,则称该方法为虚方法 (virtual method)。若其中没有 virtual 修饰符,则称该方法为非虚方法 (non-virtual method)

在调用一个虚方法时,该调用所涉及的那个实例的运行时类型 (runtime type) 确定了要被调用的究竟是该方法的哪一个实现。在非虚方法调用中,实例的编译时类型 (compile-time type) 是决定性因素。

虚方法可以在派生类中重写 (override)。当某个实例方法声明包括 override 修饰符时,该方法将重写所继承的具有相同签名的虚方法。虚方法声明用于引入新方法,而重写方法声明则用于使现有的继承虚方法专用化(通过提供该方法的新实现)。

抽象 (abstract) 方法是没有实现的虚方法。抽象方法使用 abstract 修饰符进行声明,并且只有在同样被声明为 abstract 的类中才允许出现。抽象方法必须在每个非抽象派生类中重写。

下面的示例声明一个抽象类 Expression,它表示一个表达式树节点;它有三个派生类 Constant、VariableReference 和 Operation,它们分别实现了常量、变量引用和算术运算的表达式树节点。

using System;
using System.Collections;

public abstract class Expression
{
public abstract double Evaluate(Hashtable vars);
}

public class Constant: Expression
{
double value;

public Constant(double value) {
this.value = value;
}

public override double Evaluate(Hashtable vars) {
return value;
}
}

public class VariableReference: Expression
{
string name;

public VariableReference(string name) {
this.name = name;
}

public override double Evaluate(Hashtable vars) {
object value = vars[name];
if (value == null) {
     throw new Exception("Unknown variable: " + name);
     }
return Convert.ToDouble(value);
}
}

public class Operation: Expression
{
Expression left;
char op;
Expression right;

public Operation(Expression left, char op, Expression right) {
this.left = left;
this.op = op;
this.right = right;
}

public override double Evaluate(Hashtable vars) {
double x = left.Evaluate(vars);
double y = right.Evaluate(vars);
switch (op) {
     case '+': return x + y;
     case '-': return x - y;
     case '*': return x * y;
     case '/': return x / y;
     }
throw new Exception("Unknown operator");
}
}

上面的四个类可用于为算术表达式建模。例如,使用这些类的实例,表达式

x + 3 可如下表示。

Expression e = new Operation(
new VariableReference("x"),
'+',
new Constant(3));

Expression 实例的 Evaluate 方法将被调用,以计算给定的表达式的值,从而产生一个 double 值。该方法接受一个包含变量名称(作为哈希表项的键)和值(作为项的值)的 Hashtable 作为参数。Evaluate 方法是一个虚抽象方法,意味着非抽象派生类必须重写该方法以提供具体的实现。

Constant 的 Evaluate 实现只是返回所存储的常量。VariableReference 的实现在哈希表中查找变量名称,并返回产生的值。Operation 的实现先对左操作数和右操作数求值(通过递归调用它们的 Evaluate 方法),然后执行给定的算术运算。

下面的程序使用 Expression 类,对于不同的 x 和 y 值,计算表达式 x * (y + 2) 的值。

using System;
using System.Collections;

class Test
{
static void Main() {

Expression e = new Operation(
     new VariableReference("x"),
     '*',
     new Operation(
     new VariableReference("y"),
     '+',
     new Constant(2)
     )
);

Hashtable vars = new Hashtable();

vars["x"] = 3;
vars["y"] = 5;
Console.WriteLine(e.Evaluate(vars)); // Outputs "21"

vars["x"] = 1.5;
vars["y"] = 9;
Console.WriteLine(e.Evaluate(vars)); // Outputs "16.5"
   }
}

转载于:https://www.cnblogs.com/freebird92/archive/2006/12/28/605965.html

虚方法、重写方法和抽象方法[转载]相关推荐

  1. Objective-c 类的继承 方法重写 方法重载

    一.类的继承 Objective-c中类的继承与C++类似,不同的是Objective-c不支持多重继承,一个类只能有一个父类,单继承使Objective-c的继承关系很简单,易于管理程序. Obje ...

  2. JAVA入门级教学之(方法重写/方法重载)

    方法重写: package com.lbj.javase10;public class Bird extends Animal {public void move(){System.out.print ...

  3. Java Part1 Day11继承 方法重写 super多态

    面向对象 一.内容回顾 封装;将类内部的属性隐藏private在类的内部,通过对外的公共接口(public setxxx getxxx)去操作,切薄数据的安全(合理) 实现过程:1属性私有 2封装方法 ...

  4. Java:继承之super关键字,继承之私有权限,继承之方法重写,继承之object类,继承之简单工厂模式

    一.继承的概念及用法       继承背后的思想就是        基于已存在的类来构建新类         当从已存在类继承时,就重用了它的方法和属性,还可以添加新的方法和属性来定制新类以应对需求 ...

  5. 第三次学JAVA再学不好就吃翔(part32)--方法重写

    学习笔记,仅供参考 文章目录 面向对象 方法重写 方法重写的注意事项 面向对象 方法重写 什么是方法重写 重写:子父类出现了一模一样的方法 方法重写的应用: 当子类需要父类的功能,而功能主体子类有自己 ...

  6. Java方法重写与重载

    目录 一.方法重载(overload) 概念 注意 二.方法重写(0verride) 概念 方法重写的应用场景 @Override注解 注意 三.重写与重载区别 访问修饰符 一.方法重载(overlo ...

  7. JAVA中的方法重载(Overloading)和方法重写(Overriding)

    一. 方法重载 方法重载:当同一个类中有两个或两个以上相同命名的方法. 当方法重载时,必须要保证每两个方法之前的方法签名(Signature)是不同的.这意味着这两个方法有着不同数量的参数或者参数的类 ...

  8. Java基础【之】面向对象编程(封装、继承(extends、方法重写、super)、多态(动态绑定、重载/重写)、代码实现)

    Java基础[之]面向对象编程(封装.继承.多态.代码实现) 1.封装 2.继承 2.1.extends 2.2.方法重写 2.3.super 3.多态 3.1.对象的多态.方法的多态 3.2.动态绑 ...

  9. Java基础方法重写

    文章目录 关于java语言当中的方法的覆盖 关于java语言当中的方法重载 示例代码: 关于java语言当中的方法的覆盖 1.方法覆盖又被称为方法重写,英语单词:override[官方]/overri ...

  10. Java 继承中的属性隐藏与方法重写

    一.变量隐藏--变量不具有多态性 Java 中的变量不遵循多态性,所以重写仅适用于方法,而不适用于变量. 并且,当子类中的实例变量与父类中的实例变量具有相同的名称时,则从引用类型中选择该实例变量. 在 ...

最新文章

  1. Linux 安全基线
  2. php接收arduino向服务器发来的请求
  3. verilog HDL 编码风格
  4. HDU 1213 How Many Tables(并查集模板)
  5. Kubernetes事件离线工具kube-eventer正式开源
  6. 面试官:说说你知道多少种线程池拒绝策略
  7. MySQL(22)--- NULL 值处理
  8. android 8.0 行为变更--day03
  9. LeetCode(2)——两数相加(JavaScript)
  10. bzoj1833: [ZJOI2010]count 数字计数(数位dp)
  11. GoldenGate 12.3 MA架构介绍系列(4)–Restful API介绍
  12. microsoft visual c++与microsoft visual net 版本对应关系
  13. 软件设计师(中级)历年真题与知识点总结(更新中...)
  14. 学科竞赛管理系统服务器错误,学科竞赛管理系统.docx
  15. Python深度学习(3):波士顿房价预测
  16. Linux从删库到跑路--常用命令
  17. 7*24小时全球实时财经新闻直播摘要python抓取
  18. 显卡优化以提高计算机性能,《绝地求生》完美显卡优化教程:低配电脑也能吃鸡无压力!...
  19. Chinaz:谈谈近期的安全事件
  20. 医学影像设备学_【技士/师证考试宝典】第四篇 医学影像设备学CR 11

热门文章

  1. 确定第十五届安徽赛区国赛奖项数量
  2. 面包板上的高频放大电路
  3. 任艳频 | 竞赛12年纪念文集--后记
  4. php dir opendir,php opendir()列出目录下文件的方法代码
  5. 服务器负载不高 响应慢_负载均衡有哪几大类别?
  6. androidsettitle方法_Android使用setCustomTitle()方法自定义对话框标题
  7. python导入包相当于什么_Python 引入包的两种方式区别
  8. 在ubuntu上使用gdb-multiarch 跨平台调试
  9. readline 移植 注意事项
  10. android 定义date对象,如何从Date对象设置Android Chronometer基准时间?