面向对象的三大特性是封装、继承、多态,C#和Java都是面向对象的语言所以他们的类、继承、重写与多态有很多共同点,但是实现上也存在一定的区别。其中Java中其实没有虚函数的概念,也可以认为Java的函数默认都是虚函数都可以被重写;而在C#中要用关键字virtual指明特定的函数为虚函数才可以实现重写。

多态

多态的意思的一个接口或对象的变量在运行时可以有多种不同的形态,这是通过运行时绑定(晚绑定)实现的。

一个接口或对象的变量在运行时可以动态地指向多个对象中的一个,所以多态的结果是直到运行的那一刻才知道具体执行的是哪个对象的方法。

通过继承接口实现多态

假如有一个接口A,A中有一个方法SayHi(),然后B和C实现了接口A,关系如下:

A <- B

A <- C

接口的多态:

  1. 声明一个接口A的变量:A a = null;
  2. 在运行的过程中动态地给a赋予B或C的对象
  3. 调用A的SayHi()方法,这时实现了动态地调用B或C的SayHi()

通过重写方法实现多态

重写指的是在继承的关系中,子类重写(override)了父类的相同签名的方法(相同方法名并且相同的参数)。

假如有一个类A,A中有一个虚函数(virtual)SayHi(),然后B和C继承了类A,并都重写了父类A的方法SayHi()关系如下:

A <- B

A <- C

重写的多态:

  1. 声明一个父类A的变量:A a = null;
  2. 在运行的过程中动态地给a赋予B或C的对象
  3. 调用a的SayHi()方法,这时实现了动态地调用B或C的SayHi()

C#中的重写

C#的重写必须使用关键字virtual和override,其中virtual用于父类的方法,指明该方法为虚函数,override用于子类的相应方法,指明该方法重写父类的方法。

class Program
{
static void Main(string[] args)
{
BaseClass obj = new DerivedClass();
obj.SayHi();
Console.ReadKey();
} class BaseClass
{
public virtual void SayHi()
{
Console.WriteLine("Hi Base.");
}
} class DerivedClass : BaseClass
{
public override void SayHi()
{
Console.WriteLine("Hi Derived.");
}
}
}

输出:

Hi Derived.

Java中的重写

java默认所有的方法都是虚函数(可以通过final关键字把方法声明为非虚函数),默认都可以被重写,所以java的重写要比C#简单一些:

public class Example {
public static void main(String[] args) {
BaseClass base = new DerivedClass();
base.SayHi();
}
} class BaseClass {
public void sayHi() {
System.out.println("Hi Base.");
}
} class DerivedClass extends BaseClass {
public void sayHi() {
System.out.println("Hi Derived.");
}
}

输出:

Hi Derived.

C#特有的new修饰符

C#的new修饰符的作用有点难以理解,官方定义是用于隐藏父类具有同签名的方法,隐藏是针对子类的,可以简单理解为:

声明一个和父类具有同样签名的方法并告诉编译器我这个方法和父类的方法没有任何联系。

单单从定义看很难理解它的真正含义,用代码来说话:

class Program
{
static void Main(string[] args)
{
BaseClass obj1 = new DerivedClass();
obj1.SayHi(); DerivedClass obj2 = new DerivedClass();
obj2.SayHi(); Console.ReadKey();
} class BaseClass
{
public void SayHi()
{
Console.WriteLine("Hi Base.");
}
} class DerivedClass : BaseClass
{
public new void SayHi()
{
Console.WriteLine("Hi Derived.");
}
}
}

输出:

Hi Base.
Hi Derived.

由运行结果可以看出来,obj1变量虽然在运行的过程中被赋予了DerivedClass对象,但是在调用SayHi()的时候实际是是调用了BaseClass的SayHi()。

结果分析:

  1. 因为new修饰的方法只是隐藏,SayHi()没有被重载,所以obj1的输出是:"Hi Base.",注意这是new修饰词的一个不好理解的坑。
  2. 在子类中用新的SayHi()隐藏了父类的SayHi(),所以obj2的输出是:"Hi Derived."

由此可见:

隐藏与多态无关

override和new的区别:

  • override要和virtual配合使用,而new并不需要(new也可以隐藏非虚函数)
  • 用virtual/override是为了实现多态,而new恰好相反

总结

从语法上看Java的重写与多态在实现上要比C#简洁一些,没有那么多的关键字,也没有那么多复杂难懂的语法。但是C#比Java多了一个特性就是子类可以拥有一个和父类具有同样签名的新方法,费那么多力气去换一个也不是太常用的特性是不是有点不值得呢。

转载请注明出处:http://www.cnblogs.com/keitsi/p/6137605.html

C#和Java的类、继承、重写与多态的更多相关文章

  1. java一个类 继承HttpServlet 和实现Servlet区别

    java一个类 继承HttpServlet 和实现Servlet区别 servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法 而HttpServlet实现了servlet接 ...

  2. 【JAVA】类继承对父类静态变量的操作

    对静态变量的操作存在继承时还是有一些模糊,做了个简单的测试: class Test { private String mName; public Test(String name) { setName ...

  3. Java的类继承

    知识点1.继承作用:提高代码的重用性,继承之后子类可以继承父类中的属性和方法减少重复代码条件:子类和父类要满足is a的逻辑关系,才能使用继承.如:苹果 is a水果语法:使用extends 连接子类 ...

  4. java的类继承(与c++对比)

    1. interface的引入 使用interface来定义某一类通用操作,而又不强制规定其实现,对于Java的流行真是太重要了. 以JDBC举例.在Java之前,C++与数据库建立连接,常用的一个技 ...

  5. java基础 类 & 继承

    类 在Java中,类文件是以.java为后缀的代码文件,在每个类文件中可以有多个类,但是最多只允许出现一个public类,当有public类的时候,类文件的名称必须和public类的名称相同,若不存在 ...

  6. 为什么java实体类需要重写toString方法

    如果没重写toString的情况: Object 类的 toString 方法 返回一个字符串,该字符串由类名(对象是该类的一个实例).at 标记符“@”和此对象哈希码的无符号十六进制表示组成.换句话 ...

  7. C++ 和 Java 对类继承的差异

    #include <iostream> using namespace std; class Base { public: int i; Base() { i = ; fun(); } v ...

  8. Java: 类继承中 super关键字

    super 关键字的作用有两个: 1)在子类中调用超类的构造器,完成实例域参数的初始化,调用构造器的语句只能作为另一个构造器(通常指的是子类构造器)的第一条语句出现, 2)在子类中调用超类的方法,如: ...

  9. Java面向对象之继承,方法重写,super关键字,员工类系列继承题

    在程序中,如果想声明一个类继承另一个类,需要使用extends关键字. 格式: class 子类 extends 父类 {} 继承的好处 1.继承的出现提高了代码的复用性,提高软件开发效率. 2.继承 ...

随机推荐

  1. Converter -> public static int ToInt32(double value) 你用对了么?

    Convert.ToInt32()  是我们经常使用的方法,但如果我们写如下的代码,能确定它的输出值么? var x = 7.5; Console.WriteLine(7.5 + ": &q ...

  2. HTML+JavaScript实现链式运动特效

    在学习js的过程中,发现这家伙做特效真是不错,尽管说眼下水平还不够,只是也能写点简单的效果. 今天分享一个简单的运动框架.然后利用这个框架实现简单的链式运动特效. 1.move.js 在运动框架中.主 ...

  3. Git学习笔记四--远程仓库

    Git远程仓库 Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上. 怎么分布呢?最早,肯定只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本 ...

  4. mybatis 表情存储报错问题解决

    修改mysql配置文件my.cnf(windows为my.ini) mac brew方式在/usr/local/etc/my.cnf my.cnf一般在etc/mysql/my.cnf位置.找到后请在 ...

  5. 约瑟夫环 java实现

    问题: N个人从1到N编号.围城一圈,从1開始报数, 数到X时,将X的编号输出,并将那个人踢出, 下一个从1再開始报数,直到全部人都出去 思路: 就是计数.移除,没有太深的思想,直接上代码: pack ...

  6. javascript-使用el表达式获取后台传递的数据

      js获取后台数据 CreateTime--2017年5月26日16:14:14Author:Marydon 在js中使用el表达式的前提是:HTML引用js使用内联方式(即在JSP页面内部使用js ...

  7. gulp入门学习教程(入门学习记录)

    前言 最近在通过教学视频学习angularjs,其中有gulp的教学部分,对其的介绍为可以对文件进行合并,压缩,格式化,监听,测试,检查等操作时,看到前三种功能我的心理思想是,网上有很多在线压缩,在线 ...

  8. 将项目从tomcat 迁移到JBoss5.0

    http://java-boy.iteye.com/blog/531411从Tomcat升级到JBoss5.1真是一个痛苦的过程,可能遇到很多问题.以下是我碰到的问题,及解决方法. 一.Hiberna ...

  9. django inspectdb

    使用inspectdb  --通过已有数据库表生成 model.pyinspectdb辅助工具检查你的settings文件指向的数据库,决定你表示你的表的Django模型并打印Python模型代码到标 ...

  10. sql server 使用for xml path 将1列多行转换为字符串连接起来

    create table tb ([id] )) insert into tb ,'aa' union all ,'bb' union all ,'cc' union all ,'dd' union ...