A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 有你珍贵 于 2013-10-29 21:29 编辑

      昨天刚学的抽象类,感觉和虚方法弄混了.不知道什么时候该用抽象类. 什么时候该用虚方法来实现多态.求大神解答

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

7 个回复

倒序浏览
首先你应该理解类和方法不是同一级别的,类可以包含方法!
一..抽象方法就是在声明方法时加上abstract关键字,要注意以下两点:
1. 抽象方法必须声明在抽象类中
2. 声明抽象方法时,不能使用virtual  static  private 修饰符
抽象方法声明引入了一个新方法,但不提供该方法的实现,由于抽象方法不提供方法的实现 ,因此抽象方法的方法体只能包含一个分号.
当从抽象类派生一个非抽象类时,需要在非抽象类中重写抽象方法,以提供方法的实现,重写抽象方法时使用override关键字.
二..虚方法  当类中的方法声明前加上了virtual修饰符时,我们称之为虚方法.
什么时候用虚方法?  若希望或预料到基类的这个方法在将来的派生类中会被重写时,则此方法必须声明为virtual.
override重写继承自基类的虚方法,可以理解为拆掉老房子,在原地址上建新房子,这样老房子再也找不到了(即基类中的虚方法永远调用 不到了).

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

回复 使用道具 举报
虚方法  
public class  abc
{
public virtual int a()
{
     里面的方法体是可以实习的
}
}
抽象方法只能在抽象类中声明
public  abstract  class abc
{
     public  abstract   int a();  这里的方法不能实现   只能在重写的时候实现
}

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

回复 使用道具 举报
抽象类:
  当某类中定了抽象方法,则该类须定义成抽象类,定义的抽象方法无须写方法体,该抽象类无法实例化,当然在抽象类中可以定义其他属性和非抽象方法
abstract class AbstractClass
    {
        public abstract void SayHi();
        public static void SayHello() {
            Console.WriteLine("hello!");
        }
    }
当某新类继承与抽象类,则这新类需要重新抽象类的抽象方法
   class NewClass:AbstractClass
    {
        public override void SayHi()//public override系统会自动提示要重新的方法有哪些
        {
            throw new NotImplementedException();//方法体
        }
    }

虚方法:类中的方法声明前加上了virtual修饰符
      当基类的这个方法在将来的派生类中会被重写时,则此方法必须声明为virtual.
class NewClass:AbstractClass
    {
        public override void SayHi()//重写了抽象方法
        {
           // throw new NotImplementedException();
            Console.WriteLine("hi!");
        }
        public virtual void SayHello() {//虚方法,重写了基类中的SayHello方法
            Console.WriteLine("new hello!");
        }
    }

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

回复 使用道具 举报
什么时候用抽象方法,什么时候用虚方法么?
说下我的理解:
抽象就是不具体么
所以只需声明一下方法,具体方法内容不必填写,抽象方法位于抽象类中,抽象类可以认为是一种完全为子类服务的类,实际是不“存在”这个类的,所以不能实例化这个类,当然这个“存在”还是“不存在”是根据需要而决定的。
比如:一个问题,其中只有老师,学生和校长三个类,每个类都有不同的说话方法,但是都有相同的走路和吃饭方法。这个问题中不会存在其他类了,那么我们可以抽象出一个“人类”作为这三个类的父类(由于这个问题中并不“存在”人类,人类只是服务与老师类,学生类和校长类的,所以不能实例化人类),人类中写全走路和吃饭方法,声明下说话方法,说话方法前面用abseract修饰。这样,当我们写老师,学生和校长类的时候,就不用写走路和吃饭方法了,只要写每个类自己的说话方法,前面用override修饰就OK了。简化了程序。

虚指的是被遮住的
当你觉得你这个方法,对于你的某些子类,可能不是很适用的时候,你就可以在这个方法的声明前面加virtual(注意,抽象方法和这里是不一样的,抽象方法是你这个方法根本没必要去写,因为你的不同子类,你可以很确定的知道它们的这个方法都是不一样的,你这里写什么都不合理,所以干脆不写了,让你的每个子类自己去写自己的这个方法),这样对于你的子类,就可以重写这个方法,重写时方法明相同,前面加override,这样子类这个方法名的方法时,就会调用这个重写后的方法。

举个例子:
我们可以定义一个类:外星人,并且给他定义一个说话的方法
够抽象吧,对于外星生命体怎么说话都是可能的,所以我们无法详细写出它的说话方法,此时,仅仅声明了这个说话方法,并没有填写其中内容,这就是抽象方法了,抽象方法只能位于抽象类中,那么外星人就是一个抽象类了(根据我们的需要,外星人就不“存在”了)。
我们又定义了火星人继承自外星人。
假设我们对火星人有一定程度的了解了,知道他们是用头上的触角说话,但是我们又不确定,任何地方的火星人都是用触角说话的,所以我们这里就把说话方法前面用virtual修饰,方便以后发现了变种火星人去重写它的说话方法。
比如,火星人一共有两种:地上火星人和天上火星人,他们都继承自火星人,而且都是用触角说话,那么对于这两种火星人,他们父类的说话方法就可以正常用。
如果我们发现,水里的火星人是用嘴说话的,而其他特征没什么特点。我们就可以定义水里火星人这个类,让它继承自火星人这个类,重写它的说话方法。一切就OK了

我理解就是,当子类的这个方法均不相同的时候,父类的这个方法写成抽象方法就比较合适。
当我们不确定某些子类的这个方法是不是会有所不同时,就将这个方法写成虚方法,方便一些特殊子类重写这个方法。或者当我们确定子类的这个方法虽然不是完全一样,但是也有很多子类共用相同方法的时候,我们将使用次数最多的那个方法写在父类中,并且写为虚方法,这样就会用很多的子类不必再写这个方法,直接从父类继承即可,对于那些不一样的,可以重写这个方法。

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

回复 使用道具 举报
一.首先你应该理解抽象类和虚方法不是一个级别,类中包含方法

二.分别介绍两个东东

1 [b.抽象类: 用关键字abstract
   作用就是产生子类时给予子类一些特定的方法和属性,那么什么时候用呢?  当你的类中有某些方法是共同的,而有些方法是因对象而异,那么就要将此方法声明为抽象方法,那么其对应的类就是抽象类。
  特性:
a.抽象类不能被实例化;
b.抽象类可以包含抽象方法和抽象访问器;
c.不能用sealed修饰符修改抽象类,这意味着抽象类不能被继承;
d.从抽象类派生的飞抽象类必须包括继承的所有抽象方法和抽象访问器的实现。

2.虚方法:用关键字 virtual
   虚方法就是可以被子类重写的方法,那么什么时候用呢? 如果子类重写了虚方法,那么运行时将使用重写后的逻辑,如果没有重写,则使用父类中虚方法的逻辑;

3.顺便帮你总结一下:抽象方法和虚方法的区别:

抽象方法和虚方法的区别 :
二者的区别在于:虚拟方法有一个实现部分,并为派生类提供了覆盖该方法的选项,相反,抽象方法没有提供实现部分,强制派生类覆盖方法(否则 派生类不能成为具体类);
~abstract方法只能在抽象类中声明,虚方法则不是;
~abstract方法必须在派生类中重写,而virtual则不必;
~abstract方法不能声明方法实体,虚方法则可以。

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 念念念念_、 于 2013-10-29 16:49 编辑

什么叫抽象类??
就是“只说不做的”,   不能被实例化(不能new)
比如动物都有一个eat和bark方法。但是由于每个动物的eat和bark是不一样的,所以父类中定义的方法是不需要被实例化的,这时就可以把它们定义成抽象类。由子类继承父类并重写这些方法。

1、抽象方法不能有任何的方法体。

2、抽象成员必须标记为abstract

3、抽象成员必须包含在抽象类中,不能写在一个实例中

4、并且抽象成员不能是私有的(private)

5、抽象类中可以包含实例成员

6、抽象类是不能被实例化的(抽象类的作用就是让继承)

7、子类继承抽象类后,必须重写父类中的所有抽象成员(除非子类也是一个抽象类,则可以不重写)

8、抽象类是有构造函数的,虽然不能被实例化

9、抽象类的目的:为了重写,即实现多态(代码重用)


-----------------------------------------------------------------------------

如果父类中的方法有默认实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。

如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类





用虚方法实现多态

class Program
    {
        static void Main(string[] args)
        {
             //开放封闭原则:对扩展开放,对修改关闭原则

            Chinese ch = new Chinese("张三");
            Japanese ja = new Japanese("松下井田");
            American am = new American("Tom");
            //由于多个子类对象,那么声明一个父类的对象就能将子类的
            //对象一一放进来存放。
            Person[] per = new Person[] { ch, ja, am };

         
            for (int i = 0; i < per.Length; i++)
            {

                //如果随着人的不断增加,那么这个代码就要一直往下写。很麻烦
                #region 旧代码
                //由于person类中没有Say方法。所以是点不出来的
                //per.

                //if (per is Chinese)
                //{
                //    Chinese c = (Chinese)per;
                //    c.Say();
                //}
                //else if (per is Japanese)
                //{
                //    Japanese j = (Japanese)per;
                //    j.Say();
                //}
                //else
                //{
                //    American a = (American)per;
                //    a.Say();
                //}
                #endregion

                //这样就只要一句话的代码就能搞定
                //这就体现了多态
                per.Say();

            }
            Console.WriteLine();
            Console.ReadKey();
        }
    }




class Japanese:Person
    {
        public Japanese(string name)
            : base(name)
        {

        }
        public override void Say()
        {
            Console.WriteLine("我叫{0},我是日本人!", Name);
        }
    }


class Chinese : Person
    {
        public Chinese(string name):base(name)
        {
            this.Name = name;
        }
        //如果子类要重写父类的方法,那么要在子类方法名前 加一个override关键字,如下
        //并且有且仅有这个一个关键字重写父类的方法

        public override void Say()
        {
            Console.WriteLine("我叫{0},我是中国人!",Name);
        }
    }



class American : Person
    {
        public American(string name):base(name)
        {
            this.Name = name;
        }
        public override void Say()
        {
            Console.WriteLine("我叫{0},我是美国人!", Name);
        }
    }



public class Person
    {
        public Person(string name)
        {
            this.Name = name;
        }

        public string Name
        {
            get;
            set;
        }
        //virtual关键字是标记为虚方法用的
        //如果一个方法是虚方法,那么这个方法在子类中就可以被重写了
        //子类继承父类后,可以直接使用父类的方法,也可以将它重写 (用关键字override即可)
        public virtual void Say()
        {
            Console.WriteLine("父类中的Say方法");
        }
    }

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 吴彤辉 于 2013-10-29 17:42 编辑

1.使用虚方法实现多态
  1. class A   
  2.   {         
  3.        public virtual void F()     
  4.     {        
  5.        Console.WriteLine("A.F");      
  6.      }   
  7. }     
  8. class B : A   
  9. {      
  10.    public override void F()     
  11.     {            
  12. Console.WriteLine("B.F");        
  13. }   
  14. }      
  15. class Test     
  16. {         
  17. static void Main(string[] args)   
  18.       {              B b = new B();         
  19.                    A a = b;//类型转换              
  20.                    a.F();           
  21.                    b.F();                 
  22.                   Console.ReadLine();      
  23.    }
  24. }
复制代码
2.使用抽象方法实现多态
  1. 例1:抽象类不能实例化
  2. abstract  class A     {             }
  3.     class Test     {
  4.         static void Main(string[] args)     
  5.     {            
  6.             A a =new A();//无法创建抽象类的实例                     
  7.            Console.ReadLine();      
  8.   }
  9. }  
  10. 例2:抽象类可以被继承   
  11. abstract  class A     {             }
  12.    class B : A    {    }
  13.     class Test   
  14.   {
  15.     static void Main(string[] args)     
  16.     {            
  17.             B b =new B();            
  18.            Console.ReadLine();     
  19.     }
  20. }
复制代码
抽象类确定了子类的基本结构和意义,从而使程序框架更容易建立。 抽象类的特性:
1. 抽象类不能实例化
2. 抽象类可以包含抽象方法和抽象访问器,也可以包含非抽象的成员 3. 不能用sealed修饰符修改抽象类,这意味着抽象类不能被继承
4. 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实现
抽象方法和虚方法的区别
1. 虚拟方法有一个实现部分,并为派生类提供了覆盖该方法的选项,相反,抽象方法没有
提供实现部分,强制派生类覆盖方法(否则派生类不能成为具体类) 2. Abstract方法只能在抽象类中声明,虚方法则不是 3. Abstract方法必须在派生类中重写,而虚方法则不必 4. Abstract方法不能声明方法实体,虚方法则可以
5. 包含abstract方法的类不能被实例化,而包含virtual的类则可以

评分

参与人数 1技术分 +1 收起 理由
茹化肖 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马