当前位置:编程学习 > C#/ASP.NET >>

关于类的虚函数和抽象方法,在线等

首先说一下类,有一个机械类,机械类派生了很多类如机床,搭吊等,还有一个抽象类(车)。车派生了各种车。其中机械类有一个虚方法移动(在里面实现了被拉走的方法,就些就是针对除车以外使用的。),然后我同样想在车类重写移动方法,并且要写成抽象方法,不知道怎么写了,以前我曾经看个一篇文章,就是父类是虚方法,子类将重写将抽象该方法。谢谢各位 --------------------编程问答-------------------- 重写就是为了实现,重写成抽象方法是毫无意义的需求。如果你希望定义一个抽象方法,那么应该new,而不是重写。 --------------------编程问答-------------------- 之所有机械类要写成虚函数,是因为象机床,搭吊,就直接使用机械类的移动方法。然后车类下面要写成抽象类是为了团队协作。因为后面车类的移动必需要实现,并且我曾经看过这机的写法。 --------------------编程问答-------------------- 我知道怎么写了,只是不知道效果如何。
abstract class Car: Machinery 
    {
        protected abstract override void Move();
        
    } --------------------编程问答-------------------- 对不起,我只能被遗憾地告诉你,你是在“滥用”继承。

如果类型A从类型B继承,那么我们自然而然地是想告诉别人:B的东西都可以继承到A。

而你说什么“其中机械类有一个虚方法移动(在里面实现了被拉走的方法,就些就是针对除车以外使用的。)”。这就好像说“猪”有个哺乳特性,于是你说“女人是猪”。尽管你知道你的“猪”有个特性叫做“拉到市场上宰杀”,而女人并没有这个特性。

如果设计中偶尔我们不得不有一点瑕疵,那么也许可以容许。但是如果你明明知道你得“车”根本不具有你的“机械”中许多特性,那么要么你的机械类过于垃圾,要么你的车类过于空洞,总之他们不是自然而然的继承关系,此时你容许这种巨大的瑕疵,它就不是什么瑕疵了,而是滥用继承了。

我不知道你的设计中应该如何设计,因为谁也无法仅凭三言两语代替你进行系统分析。软件设计经常需要重构,每一个人都有不同的设计。如果你“敢”说“车不是机械、机械中有许多特性是车所不具有的”,那么我想在你的心目中,车就根本不是机械。既然如此,你干么非要勉为其难地让车从机械继承呢?

你这个问题,按照你的逻辑来推理,那么任何所谓“解决”我认为都是“危险、诡异”和“混乱”的。 --------------------编程问答--------------------
引用 3 楼 enaking 的回复:
我知道怎么写了,只是不知道效果如何。
abstract class Car: Machinery 
    {
        protected abstract override void Move();
        
    }


写一两行代码算是什么呢?关键是你的代码背后的概念是否恰当。

这是一个原则:不要为了少写一两行代码、为了继承一个方法,而滥用继承。

我们使用继承,是因为从业务领域角度进行分析从而得知适合使用“继承”,而不是为了什么编程方便。 --------------------编程问答--------------------
引用 4 楼 sp1234 的回复:
对不起,我只能被遗憾地告诉你,你是在“滥用”继承。

如果类型A从类型B继承,那么我们自然而然地是想告诉别人:B的东西都可以继承到A。

而你说什么“其中机械类有一个虚方法移动(在里面实现了被拉走的方法,就些就是针对除车以外使用的。)”。这就好像说“猪”有个哺乳特性,于是你说“女人是猪”。尽管你知道你的“猪”有个特性叫做“拉到市场上宰杀”,而女人并没有这个特性。

如果设计中偶尔我们不得不有一点瑕疵,那么也许可以容许。但是如果你明明知道你得“车”根本不具有你的“机械”中许多特性,那么要么你的机械类过于垃圾,要么你的车类过于空洞,总之他们不是自然而然的继承关系,此时你容许这种巨大的瑕疵,它就不是什么瑕疵了,而是滥用继承了。

我不知道你的设计中应该如何设计,因为谁也无法仅凭三言两语代替你进行系统分析。软件设计经常需要重构,每一个人都有不同的设计。如果你“敢”说“车不是机械、机械中有许多特性是车所不具有的”,那么我想在你的心目中,车就根本不是机械。既然如此,你干么非要勉为其难地让车从机械继承呢?

你这个问题,按照你的逻辑来推理,那么任何所谓“解决”我认为都是“危险、诡异”和“混乱”的。


楼上大哥,我经常看到你在网上回复,也有可能我的设计不是一两句能说清楚,有两点我要先否定你。1、在我的设计中,车类是机械类子类,我是认为车是机械中的一种。可能我这个例子不太合适;2、我现在只是在探索中,所以不为了是继承一个方法,非常多,所以需要抽象方法,主要提醒下面程序员写一个新类需要实现哪些方法。就拿你所谓动物来说吧。动物类实现了一个吃的虚方法,然后鸟类,兽类,这些吃的方法可以继承动物的吃方法,但人类有很多方法和动物一样,所以应该继承动物类,但有部分需要重写。吃的方法却需要另外实现。印度人、欧洲人、中国人都有吃饭这个方法,但吃的实现不一样,所以需要抽象方法。为了给你更好的理解,附上一段代码,谢谢指教和讨论

  
class EleBase
 {
        public void a()
        {
            KeyDownEsc();
        }
        protected virtual void KeyDownEsc()
        {
            MessageBox.Show("EleBaseText");
        }
 } 

abstract class EleText : EleBase
 {
                
 }
abstract class EleCheck : EleBase
 {
                
 }

abstract class EleSelect : EleBase
 {
        protected abstract override void KeyDownEsc();        
 } 
class EleDate : EleSelect
 {
        protected override void KeyDownEsc()
        {
            MessageBox.Show("EleDate");
        }
 }
class EleSelectItem: EleSelect
 {
        protected override void KeyDownEsc()
        {
            MessageBox.Show("EleSelectItem");
        }
 }

private void button8_Click(object sender, EventArgs e)
        {
            EleDate tst= new EleDate();
            tst.a();
        }
private void button8_Click(object sender, EventArgs e)
        {
            EleText tst= new EleText ();
            tst.a();
        }

--------------------编程问答-------------------- 上面代码有点小错,
class EleBase
 {
        public void a()
        {
            KeyDownEsc();
        }
        protected virtual void KeyDownEsc()
        {
            MessageBox.Show("EleBaseText");
        }
 } 

 class EleText : EleBase
 {
                
 }

 class EleCheck : EleBase
 {
                
 }


abstract class EleSelect : EleBase
 {
        protected abstract override void KeyDownEsc();        
 } 

class EleDate : EleSelect
 {
        protected override void KeyDownEsc()
        {
            MessageBox.Show("EleDate");
        }
 }

class EleSelectItem: EleSelect
 {
        protected override void KeyDownEsc()
        {
            MessageBox.Show("EleSelectItem");
        }
 }

private void button8_Click(object sender, EventArgs e)
        {
            EleDate tst= new EleDate();
            tst.a();
        }

private void button8_Click(object sender, EventArgs e)
        {
            EleText tst= new EleText ();
            tst.a();
        } --------------------编程问答-------------------- 其中机械类有一个虚方法移动(在里面实现了被拉走的方法,就些就是针对除车以外使用的。

class 机械{ virtual void 移动(); }
class 车  { abstact new void 移动();}
使用new之后,对于车的子类,机械.移动()就被“隐藏”了,就是你要的 --------------------编程问答-------------------- class 车 : 机械 --------------------编程问答--------------------
引用 8 楼 dongxinxi 的回复:
其中机械类有一个虚方法移动(在里面实现了被拉走的方法,就些就是针对除车以外使用的。

class 机械{ virtual void 移动(); }
class 车  { abstact new void 移动();}
使用new之后,对于车的子类,机械.移动()就被“隐藏”了,就是你要的

看来确实我举的机械和车类不太适当,我的意思车类是机械的一种,即子类,里面还有很多方法车类是继承的,只是在代码中我没写出来而已。
在实际开发中,我就从来没用过new去覆盖过父类,可能是我的想法太片面。所以想知道原因,之所以我一直没用是因为我认为有更好的方法代替它,看代码:

class EleBase
 {       
        public virtual void KeyDownEsc()
        {
            MessageBox.Show("EleBaseText");
        }
 }
class EleText : EleBase
 {
                
 }
 class EleSelect : EleBase
 {
        public new void KeyDownEsc()
        {
            MessageBox.Show("EleSelect ");
        }
       
 } 

private void button8_Click(object sender, EventArgs e)
        {
            EleBase tst= new EleDate();
            tst.a();
        }
private void button9_Click(object sender, EventArgs e)
        {
            EleBase tst= new EleSelect();
            tst.a(); 
        }

有两问题,1、这两个结果是一样的,所以为什么复杂地去实现new来隐藏呢,2、继然EleSelect.KeyDownEsc实现了,那肯定有实现的道理,那么如何才能去调用这个实现体,这也许就是和EleText类的不同之处吧。 --------------------编程问答-------------------- 真心想不出车和吊床有什么相通的地方??难道就因为他们都是金属做的???
如果你的车和吊床真有关联之处,你可以通过组合来实现这种关联,而不是通过继承 --------------------编程问答-------------------- public class TestA
    {
        protected virtual void AAA()
        { 
        }
    }

    public abstract class TestB : TestA
    {
        protected abstract override void AAA();
    }

abstract override 这样写法是有效的 --------------------编程问答--------------------
引用 12 楼 starfd 的回复:
public class TestA
    {
        protected virtual void AAA()
        { 
        }
    }

    public abstract class TestB : TestA
    {
        protected abstract override void AAA();
    }

abstract override 这样写法是有效的

车和吊床有机械的共性。我知道你这写法有效,但我问的不这是否有效,我问的是new的实用性 --------------------编程问答-------------------- 再写一个抽象类 “可移动动物体” 作为 机械 与 车 的父类,里面加个虚方法 “移动”
......

理论上如此 --------------------编程问答-------------------- 如果 机械是车的父类,那直接重写移动方法就行了。 --------------------编程问答--------------------
引用 14 楼 acceptspf 的回复:
再写一个抽象类 “可移动动物体” 作为 机械 与 车 的父类,里面加个虚方法 “移动”
......

理论上如此

你这理论上是没错,可我们需要一个团队协做,所以还要将车类的移动写抽象类,比如小轿车是两个后轮动力,两前轮方向,内燃机驱动。拖拉机是两前轮动力,两前轮方向,柴油机驱动,探月车的移动。假如公司再来一个新人要写探火星车类。这时他只要是车类的派生类,就知道有哪些方向需要重写,因为不止移动这一个方法。这其实也是抽象类的真正目的所在。 --------------------编程问答--------------------
引用 16 楼 enaking 的回复:
Quote: 引用 14 楼 acceptspf 的回复:

再写一个抽象类 “可移动动物体” 作为 机械 与 车 的父类,里面加个虚方法 “移动”
......

理论上如此

你这理论上是没错,可我们需要一个团队协做,所以还要将车类的移动写抽象类,比如小轿车是两个后轮动力,两前轮方向,内燃机驱动。拖拉机是两前轮动力,两前轮方向,柴油机驱动,探月车的移动。假如公司再来一个新人要写探火星车类。这时他只要是车类的派生类,就知道有哪些方向需要重写,因为不止移动这一个方法。这其实也是抽象类的真正目的所在。


那在车的基础上再建前驱车,后驱车。
可能还得加发动机属性,发动机又有汽油,柴油,电力,氢气....只要不计较成本,几个树形结构就出来了... --------------------编程问答--------------------
引用 13 楼 enaking 的回复:
Quote: 引用 12 楼 starfd 的回复:

public class TestA
    {
        protected virtual void AAA()
        { 
        }
    }

    public abstract class TestB : TestA
    {
        protected abstract override void AAA();
    }

abstract override 这样写法是有效的

车和吊床有机械的共性。我知道你这写法有效,但我问的不这是否有效,我问的是new的实用性


楼主,你这段代码,abstract其实和override不应该共存的。
abstract是抽象类,
override用于重写,但只能重新标识为abstract、visual、override的类。
new是实例化,是将其定义为独立于基类的方法,这个和override是有区别的。

http://msdn.microsoft.com/zh-cn/library/6fawty39.aspx --------------------编程问答--------------------
引用 18 楼 k25566 的回复:
Quote: 引用 13 楼 enaking 的回复:

Quote: 引用 12 楼 starfd 的回复:

public class TestA
    {
        protected virtual void AAA()
        { 
        }
    }

    public abstract class TestB : TestA
    {
        protected abstract override void AAA();
    }

abstract override 这样写法是有效的

车和吊床有机械的共性。我知道你这写法有效,但我问的不这是否有效,我问的是new的实用性


楼主,你这段代码,abstract其实和override不应该共存的。
abstract是抽象类,
override用于重写,但只能重新标识为abstract、visual、override的类。
new是实例化,是将其定义为独立于基类的方法,这个和override是有区别的。

http://msdn.microsoft.com/zh-cn/library/6fawty39.aspx

错别字
override用于重写,但只能重新标识为abstract、visual、override的方法 --------------------编程问答--------------------
引用 13 楼 enaking 的回复:
Quote: 引用 12 楼 starfd 的回复:

public class TestA
    {
        protected virtual void AAA()
        { 
        }
    }

    public abstract class TestB : TestA
    {
        protected abstract override void AAA();
    }

abstract override 这样写法是有效的

车和吊床有机械的共性。我知道你这写法有效,但我问的不这是否有效,我问的是new的实用性


new 肯定不实用.....

假定 两个类
class P
{
    public void Method()
    {
       Console.WriteLine("P");
    }
}
class C:P
{
    public new void Method()
    {
       Console.WriteLine("C");
    }


P p = new C();
p.Method();
((C)p).Method();

上面的执行结果是 
P
C

new这种东西就跟goto一样,存在虽然有理,但如果不是实在没办法,不要用
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,