C#为何要用到抽象函数?

既然有了虚函数,为什么还需要抽象函数?而且虚函数不强制重写,抽象函数强制重写,当我们不需要重写函数的时候,抽象不会显得更麻烦?在我看来抽象函数用起来比虚函数要麻烦,但是它... 既然有了虚函数,为什么还需要抽象函数?而且虚函数不强制重写,抽象函数强制重写,当我们不需要重写函数的时候,抽象不会显得更麻烦?在我看来抽象函数用起来比虚函数要麻烦,但是它却存在了,那存在必定有意义,本人菜鸟还请大神、高人指点。
抽象函数能做到的,虚函数也能做到,那我还要抽象函数干嘛?有人会说含有抽象函数的类(也就是抽象类)不可以被实例,我普通类想实例就实例不想实例就不实例多自在,你抽象类不是蛋疼吗?有人会说抽象函数强制重写,在我看来根本就是多此一举,本来有些子类不需要重写这个函数的,这下好了每个子类都得重写一次,这压根就是增加程序员的代码量。抽象函数简直就是一无是处。
求喷,求侮辱
展开
 我来答
匿名用户
2015-05-01
展开全部
面向对象第一阶段,理解面向对象术语体系。楼主显然正在这样的阶段里徘徊。
-------------------------------------------------------------------------------------------------------------------------------
当然这也无怪楼主,比如楼下的回答。有些是所谓存在即合理的论调都抛出来了,这是要以道理压人啊——这分明是说,我虽然也不知道,但存在即合理。当然还是从抽象类与普通类的区别上来说了,一个强制重写,一个不强制重写,假定我们不用IDE而是用记事本编程,那么提示编程人员的重写功能似乎说不过去了,如果说编译时提醒,那么如果编译器不是那么完美呢?显然,并没有说中要害。
——————————————————————————————————————————
在面向对象的第一阶段确实不好理解,但在第二阶段,模式设计时,也许会有不少人告诉你,尽量不要用继承,因为继承的耦合性非常大,那么这时候可能自觉不自觉地去理解这些东西了。至于面向切面编程告诉你,如果你继承于一个普通类,那么一定是继承树有问题,也不会是质量较高的代码了。所以面向切面编程要求被继承的父类必须是抽象类。
——————————————————————————————————————————
先从原理说起:怎么去抽象?
如果多个类实现相同的方法,那么该方法体与签名应提升到父类中去,继承的子类就具有相同的行为,这一点可以保证被继承的子类在父类方法修改时可以同时修改。
但是如果有一些类与大多数类实现的行为不同,那么应将该方法体与签名提升到父类中,同时允许部分子类重写,也就是写成虚方法。虚方法修改时会影响到大部分类的行为,但不会影响到对虚方法重写类的行为。
如果大多数类实现有相同的签名,但几乎每个方法都不相同,则应将方法签名提升到父类,做抽象方法以提子类重写——这里有一个前提条件,就是在父类被调用或父类其他方法中对子类延迟实现的方法有调用。如果没有父类层的代替调用,那么这些完全不同行为的方法为何还要提升到父类中去呢?这样多此一举?
这句话可能难以理解一点,举个例子吧,抽象父类可能是框架结构上的元素,调用方根据迪米特法则(知识最少原则)只了解抽象父类,而各子类的实现是模块另外一个程序员开发组实现的。根据里氏代换,调用父类其实可以实现具体子类的功能,但子类的具体实现却不是调用方关心的。还有就是父类在调用层次上直接调用了某个保护函数(protected),这个函数延迟到子类实现。
现在,我们看到了这些功能上使用上区别,但显然虚方法与抽象方法似乎有着相同的功能,其实是抽象的方式不太一样,虚方法是大多子类要实现的功能,而抽象方法是几乎所有子类均实现不同的功能。这一点上似乎两者区别性不是很大,尤其是没有较高的面向对象编程经验的时候,两者看起来似乎是通用的。但是有个特定行为,更能决定两者的区别,子类重写时可能会执行base.XXX();同名方法,这个如果抽象方法是不被支持的。这里可以看到虚方法可能是部分类行为的实现(大多数类行为相同),也可能是大多数类行为的部分实现。

所以从抽象方式上可以看出,抽象方法与虚方法来源于不同抽象方式,两者其实是没有可比性的,该用到哪一种看抽象的行为一般是不会用错的。
-------------------------------------------------------------------------------------------------------------------------
再从框架说起,从原理其实是一种自底向上的分析方式,而框架则是自顶向下分析。那么接口与抽象类不能是简单的结构了,而是一个接口协议,也就是说我们使用接口或抽象类向业务实现编程人员定义协议,而由编程人员去编程实现,那么,抽象方法表示必须由实现人员实现的行为,而虚方法则是可由实现人员选择性实现的行为(这也是编译会让抽象方法不能通过编译的原因)。两者也有明显的区别。
所以框架编程上来说,两者也不会弄混,而造成误用。
————————————————————————————————————————
单纯语言层面上来,虚方法实现一个空的方法体,然后使用文档要求实现人员必须实现,其实未尝不可,也就是说虚方法单从语言方面来说,完全可以用虚方法来代替抽象方法的。当然我这里只是说单纯的语言层面上。
但一个项目工程是由易理解性(你真的能确定用虚方法代替抽象方法的理解是正确的么),易维护性(你确认其他编程人员对象的这种理解能达到同步么)等多种方面来衡量的,如果真是有较强的管理,完备的文档等那么单从语言层面上去代替是可行的。
————————————————————————————————————————
所以,如果做为程序员真着眼于语言层面,那么其实理解很多东西都是错的,就象readonly与const的区别一样,两者其实只是换种方式的实现,但对于软件工程来说,可能是一大漏洞。
————————————————————————————————————————
最后要说的是,真正的软件编程,必须保证最简继承树,或者尽量少用继承。一般情况下,继承树只要两层,除非有足够的必要,但除叶层外其他的均必须为抽象类(虽然普通类也可以继承)。所以其实继承上的问题不多,因为没有足够的理由是不用的。能提出这样的问题,至少说话程序员的态度是正确的,敏而好学,善于思考,但软件业是一个复杂行业,有些东西只有触到更高的层次才会理解,有些问题可以放一放,日后其实应该知道该怎么做,只不过可能自己也说不清楚为什么这么做而已。
超大蒲公英
2015-01-15 · TA获得超过741个赞
知道小有建树答主
回答量:758
采纳率:75%
帮助的人:742万
展开全部
你能问出这样的问题,说明已经基本理解了面向对象的特征。
抽象函数和虚函数确实都能做到多态。并且虚函数提供了默认行为,程序员可以选择性的重写。

抽象函数强制重写,这样有一个好处就是,防止程序员忘记重写,这在很大程度上从编译时就能减少程序的错误。

再有,有些函数确实没有默认行为。
DbConnection类提供的数据库连接的基类,他有一个Open方法就是抽象函数。
因为他确实不知道,Open函数该去做些什么,是要连接远程网络,还是要从本地读取文件。这些他都无法确定。就算用虚函数,方法体也只能是空的,这样反而会给程序员造成一种困扰。如果程序员忘记重写,可能会引起一些奇怪的错误表现。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
Ben
2015-06-15 · 知道合伙人软件行家
Ben
知道合伙人软件行家
采纳数:860 获赞数:2875
认真回答者.

向TA提问 私信TA
展开全部
1. 抽象类和抽象函数
C#中使用abstract关键字,将类和函数声明为抽象类或抽象函数
抽象类不能实例化,抽象函数没有执行代码,必须在非抽象的派生类中重写
抽象函数是虚拟的,但不需要提供virtual关键字,否则会报错
如果类包含抽象函受,该类将也是抽象的,也必须声明为抽象的
abstract class MyAbstract
{
// 变量的定义不适用abstract关键字
private int i;

// 属性
public abstract int count { get; set; }

// 方法
public abstract string getName();
}

简单的理解,虚函数可以被重载,基类中有实现。纯虚函数只能被重载,基类中只有定义没有实现。只要就是多态的概念,父类指针指向子类对象的时候,会执行子类中的方法。比如一个动物类,和一个人类人继承于动物 动物是基类,里面有一个死亡方法,基类有自己的实现人类里重载了基类里的死亡方法之后你写People p = new People();然后一个方法要一个动物作为参数比如杀死某个动物kill(p) 注意kill要的是animal对象p是People的对象,不过因为p继承与animal 所以可以传入kill方法里比如要调用对象的 dead()方法那么这个时候 kill方法里调用的就是People的dead()方法 而不是animal的 接口的成员函数全部都是都是纯虚函数.抽象函数和纯虚函数是一个概念 就是基类没有实现 交给子类去实现
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
zq_yxr
2015-04-21 · 超过10用户采纳过TA的回答
知道答主
回答量:42
采纳率:0%
帮助的人:22.9万
展开全部
对于虚函数我的理解如下,
打个比方: 比如一个类中有一个显示数据的方法,但这个类只提供string 的显示方法
virtual void ShowMessage(string msg)
{
//show msg
}
如果你继承了这个类,现在要显示double数据
就可以
override void ShowMessage(string msg)
{
//show string.Format("override {0}",msg);
}

抽象函数我的理解是
这个类只提供方法名称以及参数类型和名称,而不提供具体的实施方案。
每个继承它的类都要自己实现这个方法。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
匿名用户
2015-02-06
展开全部
在面向对象面前,一般都叫“方法”而不叫函数了。很明显楼主是从面向过程的编程语言中走过来的。这个比较坑一点,好好适应一下就好了。正如你所说,存在的总是有道理的。好好领悟一下,抽象方法和抽象类一样,自有它的用处。主要体现在封闭性和多态。你再想想,面向对象的三特点是啥......
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(8)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式