C#和Java的类、继承、重写与多态
面向对象的三大特性是封装、继承、多态,C#和Java都是面向对象的语言所以他们的类、继承、重写与多态有很多共同点,但是实现上也存在一定的区别。其中Java中其实没有虚函数的概念,也可以认为Java的函数默认都是虚函数都可以被重写;而在C#中要用关键字virtual指明特定的函数为虚函数才可以实现重写。
多态
多态的意思的一个接口或对象的变量在运行时可以有多种不同的形态,这是通过运行时绑定(晚绑定)实现的。
一个接口或对象的变量在运行时可以动态地指向多个对象中的一个,所以多态的结果是直到运行的那一刻才知道具体执行的是哪个对象的方法。
通过继承接口实现多态
假如有一个接口A,A中有一个方法SayHi(),然后B和C实现了接口A,关系如下:
A <- B
A <- C
接口的多态:
- 声明一个接口A的变量:A a = null;
- 在运行的过程中动态地给a赋予B或C的对象
- 调用A的SayHi()方法,这时实现了动态地调用B或C的SayHi()
通过重写方法实现多态
重写指的是在继承的关系中,子类重写(override)了父类的相同签名的方法(相同方法名并且相同的参数)。
假如有一个类A,A中有一个虚函数(virtual)SayHi(),然后B和C继承了类A,并都重写了父类A的方法SayHi()关系如下:
A <- B
A <- C
重写的多态:
- 声明一个父类A的变量:A a = null;
- 在运行的过程中动态地给a赋予B或C的对象
- 调用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()。
结果分析:
- 因为new修饰的方法只是隐藏,SayHi()没有被重载,所以obj1的输出是:"Hi Base.",注意这是new修饰词的一个不好理解的坑。
- 在子类中用新的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的类、继承、重写与多态的更多相关文章
- java一个类 继承HttpServlet 和实现Servlet区别
java一个类 继承HttpServlet 和实现Servlet区别 servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法 而HttpServlet实现了servlet接 ...
- 【JAVA】类继承对父类静态变量的操作
对静态变量的操作存在继承时还是有一些模糊,做了个简单的测试: class Test { private String mName; public Test(String name) { setName ...
- Java的类继承
知识点1.继承作用:提高代码的重用性,继承之后子类可以继承父类中的属性和方法减少重复代码条件:子类和父类要满足is a的逻辑关系,才能使用继承.如:苹果 is a水果语法:使用extends 连接子类 ...
- java的类继承(与c++对比)
1. interface的引入 使用interface来定义某一类通用操作,而又不强制规定其实现,对于Java的流行真是太重要了. 以JDBC举例.在Java之前,C++与数据库建立连接,常用的一个技 ...
- java基础 类 & 继承
类 在Java中,类文件是以.java为后缀的代码文件,在每个类文件中可以有多个类,但是最多只允许出现一个public类,当有public类的时候,类文件的名称必须和public类的名称相同,若不存在 ...
- 为什么java实体类需要重写toString方法
如果没重写toString的情况: Object 类的 toString 方法 返回一个字符串,该字符串由类名(对象是该类的一个实例).at 标记符“@”和此对象哈希码的无符号十六进制表示组成.换句话 ...
- C++ 和 Java 对类继承的差异
#include <iostream> using namespace std; class Base { public: int i; Base() { i = ; fun(); } v ...
- Java: 类继承中 super关键字
super 关键字的作用有两个: 1)在子类中调用超类的构造器,完成实例域参数的初始化,调用构造器的语句只能作为另一个构造器(通常指的是子类构造器)的第一条语句出现, 2)在子类中调用超类的方法,如: ...
- Java面向对象之继承,方法重写,super关键字,员工类系列继承题
在程序中,如果想声明一个类继承另一个类,需要使用extends关键字. 格式: class 子类 extends 父类 {} 继承的好处 1.继承的出现提高了代码的复用性,提高软件开发效率. 2.继承 ...
随机推荐
- LVS+keepalived+nginx
LVS是Linux Virtual Server的简写,基于4层协议不处理,不响应,只转发,速度更快 wget -c http://www.linuxvirtualserver.org/softwar ...
- sudo 添加
sudo 添加 /etc/sudoers 找到root ALL=(ALL) ALL那一行, 复制之后,修改用户名:
- TestNG系列之四: TestNg依赖 dependsOnMethods
有时候,你可能需要在一个特定的顺序调用方法 执行原则: 1.被依赖的先执行: 2. 再执行没配置依赖的, 3.再执行需要依赖的: 4.若无依赖关系,依次执行) 一个方法有多个依赖时用空格隔开 有两种依 ...
- 基于Thrift的跨语言、高可用、高性能、轻量级的RPC框架
功能介绍 跨语言通信 方便的使Java.Python.C++三种程序可以相互通信 负载均衡和容灾处理 方便的实现任务的分布式处理 支持服务的水平扩展,自动发现新的服务节点 能够兼容各种异常情况,如节点 ...
- HTML5 移动端如何使用css让百分比布局的弹窗水平和垂直方向上居中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- angular中使用promise
promise是一种用异步的方式处理值的方法,promise是对象,代表了一个函数最终可能的返回值或者抛出的异常,在与远程对象打交道时我们可以把他看作是远程对象的一个代理. 如果说是promise也是 ...
- 字符串在内存中的存储——C语言进阶
字符串是以ASCII字符NUL结尾的字符序列. ASCII字符NUL表示为\0.字符串通常存储在数组或者从堆上分配的内存中.只是,并不是全部的字符数组都是字符串,字符数组可能没有NUL字符. 字符数组 ...
- 算法笔记_160:算法提高 约数个数(Java)
目录 1 问题描述 2 解决方案 1 问题描述 输入一个正整数N (1 样例输入 12 样例输出 6 样例说明 12的约数包括:1,2,3,4,6,12.共6个 2 解决方案 具体代码如下: im ...
- selenium-Navigating
The first thing you’ll want to do with WebDriver is navigate to a link. The normal way to do this is ...
- E492: Not an editor command: ^M
在windows下拷贝vimrc到Linux,运行vim命令后,出现错误 vim E492: Not an editor command: ^M 原因: linux的文件换行符为\n,但windows ...