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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王乐 中级黑马   /  2012-9-19 18:05  /  5155 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

我有点不明白抽象函数的具体作用是什么,我是这样想的,既然抽象函数是注定要被子类复写的,那直接在子类中定义不行吗?非得在父类中标示1下有这么1个不清楚具体功能的函数的意义是什么?


以下附上视频教程中的1段代码,我试验了下其中MoBan类中的runcode函数不定义成抽象的也可以。那是否定义成抽象函数究竟取决于什么啊?


求解



abstract class MoBan
{
final void getTime()
{
  long starttime=System.currentTimeMillis();
  runcode();
  long endtime=System.currentTimeMillis();
  System.out.println("the time is"+(endtime-starttime));
}
abstract void runcode();
}

class Run extends MoBan
{
void runcode()
{
  for(int a=0;a<1000;a++)
  {
   System.out.print(a+"\t");
  }
}
}

class Main
{
public static void main(String[] args)
{
  Run r=new Run();
  r.getTime();
}
}

9 个回复

倒序浏览
共同学习
建立抽象类的唯一理由是:
各子型别都可以以以不同方式来表现此一共同接口。达到多态性的目的。
注意点:
* 抽象函数只能在抽象类中出现(即,一个普通的类中,不能声明抽象函数,一旦声明,要将该class用abstract做饰词,否则编译出错)
* 抽象类不能被实例化。否则编译出错。
* 只有当子类实现了抽象类中定义的所有函数,该子类才可被实例化。否则,该子类便也是个抽象类。
* 也可以将一般的类(不含任何抽象函数的类)声明为abstract。表明不允许该类产生任何实例。

评分

参与人数 1技术分 +1 收起 理由
唐志兵 + 1 赞一个!

查看全部评分

回复 使用道具 举报
给出的例子这里,主要体现了代码的复用性。

runcode里的代码变化时,至修改runcode即可。

作为父类,定义抽象方法,是因为抽象方法是给子类去用的,父类自己是不用的,所以他写也白写,干脆就不写,让子类去重写。
第一个子类的runcode是这样写的,那第二个子类的runcode可能就那样写了。

写成抽象,主要是给子类用的。
回复 使用道具 举报
在Java中抽象类的定义其实是提高了程序的扩展性。就以毕老师的例子里说把,在人类的进化史中每一个时代的人都要吃饭,都有吃饭这个功能,但是每一个时代的人吃饭的方式都有所不同,当遇到这种情况,也就需要用到抽象了,定义一个抽象的类,放入到一个抽象的吃饭的方法,让不同时代的人来具体的实现,这就提高了程序的扩展性。
还有一点,抽象类中是可以有不是抽象的 方法的,但是带有抽象方法的类一定是抽象类。
回复 使用道具 举报
抽象类是为了更好的扩展,通过继承抽象类实现多态,实现重用性等。

因为抽象类不能实例化,所以只能实例化继承它的子类。

因为实例化的是子类,子类会去实现此方法,所以在抽象类也就没必要具体实现,当然也可以实现。

如果子类不能实现抽象类的所有方法,那么子类也必须定义为抽象类。

这里需要注意的一点儿就是,抽象方法还必须是非静态的,因为不能分配内存空间

多看看书,学了接口你会更明白的
回复 使用道具 举报
当我们只知道一个方法的名称,还不知道方法里面具体要干什么的时候,我们就把这个方法定义成抽象的。例如
abstract  class Animal{void  shot();}在这个例子中,我们只知道动物要叫,但是不知道具体他怎么去叫,在以后中动物演变成了狗,我们知道了狗叫的方法,这时候我们就需要class Dog extends Animal
{public void shout()
{System.out.println("wangwang");}
}
所以,抽象方法就是为早期不能确定的那些抽取出来的,我们在以后的程序中要用到这个方法,就只去把它复写,然后增加自己的功能就行,
可以说是提高了程序的扩展性。
回复 使用道具 举报
王乐 中级黑马 2012-9-20 16:01:05
7#
谢谢大家的回答
很详细,很易懂

有这么多热心的人。这论坛真是个好地方~
回复 使用道具 举报
毕老师有个形象的说法,所谓的抽象方法,就是不明了的,暂时不知道的,也就是抽象的,所以我们在父类中可以先定义好个抽象方法,知道有这件事要做,但不知道怎样做,这时候就要用抽象方法了,所以就在父类中定义个抽象方法,等子类中知道具体该怎么做的时候再去覆写它。然后有了抽象方法后,那么该类也要为抽象的,即为抽象类。 毕老师 形象生动 讲解  希望楼主也理解 {:soso_e121:}
回复 使用道具 举报
抽象函数  其实是为了降低耦合度  方便扩张功能  比如 收费(){    }     A继承它的类后  可以写成
收费{
System.out.println(酒店收费50);
}

B继承它的类后  可以写成
收费{
System.out.println(停车收费10);
}

这样的话  就实现了更多的具体方法
回复 使用道具 举报
本帖最后由 陈振兴 于 2012-9-21 00:28 编辑

我稍微深度的讲解一下!我先以我的理解来说一下,然后从专业术语的角度来解析,可能理解起来有点吃力,但是到你后面的学习当中会很重要,重要的是这个思想。
抽象即以数据和业务逻辑来作为导向的。(
           数据,用我们现实生活中的代名词来,如家里有几口人,这就是数据的合理化抽象;
          业务逻辑,描述你需要做什么,你想要干什么,而等你干了需要达到的效果或者说目标!

以父亲,儿子为例:(稍微有点不听,但可以收到一针见血的效果)
比如祖先有个遗传病——癌症
爸爸有癌症
儿子癌症
三者的关系是,最上级先有,然后爸爸、儿子才患有的。‘就和你说的,不需要抽象他们也自己可以实现的’,但对于专业角度来讲有点数据冗余了。
而这个包括的人很多,有可能是你的爷爷,的爷爷,好几辈人都有这个,你要把这个写成代码重复好几十次,显然效率就低了,然后java中就把这个”癌症“给抽象一个方法,然后让其子类都来继承,而在每个子类当中癌症会有突变(有好的,有坏的),那么就需要抽象来让每个子类去实现。
然后在你后续学习的过程中就会体会到什么是“高类聚,低耦合!”
就是一个类与类之间,模块与模块之间的复杂度,来独立完成一项工作,而可以同时去完成,都不会产生任何影响,这就是它的本质。而最本质的就是它基于抽象的编程,接口的编程。

然后专业术语:
抽象类:abstract修饰的类
1)一旦某个类中包含有抽象方法,那这个类必须定义成抽象类。反之,如果一个类不包含任何抽象方法,这个类可以定义成抽象类。
2)抽象类不能实例化,但能定义一个引用。
3)Abstractfinal不能同时使用。

Abstract可以将子类的共性最大限度的抽取出来,放在父类中,以提高程序的简洁性。

以你此题为例,执行顺序,
先执行父类与子类中的静态代码块部分(JVM虚拟机来做的事情),父类的构造,后执行子类的构造方法。
依据是 Father f = new Person();//以这种方式来判断运行的类是哪一个,系统才会去调用哪个类的父类和子类。

以上需要你有“一段 ”时间才能理解!

评分

参与人数 1技术分 +1 收起 理由
唐志兵 + 1 赞一个!

查看全部评分

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