抽象类 抽象方法

一只红烧虾 2020-04-06 03:53:55
为什么要有抽象类呢? 抽象类中如果没有抽象方法是不是就没有意义?如果是,为什么没有意义呢? 抽象方法存在的意义又是什么呢?
...全文
509 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
android_cai_niao 2020-05-11
  • 打赏
  • 举报
回复
气死我了,上才艺!! 抽象类的意思就是说这个类上有抽象的方法,但也可以有不是抽象的方法,其实接口也是抽象类,只不过这个抽象类比较特殊,它所有的方法都是抽象的,没有不抽象的,所以就改了个说法叫接口,接口为什么可以实现多个,而的抽象类只能继承一个?原因就在于此,当你继承多个抽象类的时候,假设多个抽象类中都有相同的方法(不是抽象的方法),方法名和参数返回值都一样,只是方法的代码体不一样,这时,子类应该继承哪个抽象类上方法呢?系统没法决定,所以不能继承多个抽象类,而接口就不一样,接口的方法肯定都是抽象的,假设你实现的多个接口中一样的方法,覆盖哪个呢?有区别吗?反正他们都是抽象方法没有代码体的,覆盖哪个接口上的方法都没区别,所以可以实现多个接口。 所以,当一个父类需要有一些非抽象方法时,但又有一些是抽象方法时,使用抽象类,如果父类的所有方法是抽象的,则使用接口(当然你使用抽象类也行,只不过使用接口的话,你子类还可以继承其他类,如果使用抽象类,则你的子类不能继承其他类了)。 最后回答你为什么需要在父类中写抽象方法,示例代码如下:

    static abstract class 交通工具 {
        private String name;

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public abstract void 启动引擎();
    }
    
    static class 摩托车 extends 交通工具 {

        @Override
        public void 启动引擎() {
            // 脚踩那个东东,手上给油
        }
    }
    
    static class 汽车 extends 交通工具 {

        @Override
        public void 启动引擎() {
            // 拧开钥匙
        }
    }
作为交通工作,不管是摩托车,还是汽车,都有一个名字,这个set/getName方法写在父类,只需要写一次就行了,不然摩托车和汽车都写一遍就有点重复了。 启动引擎,做为父类,他是不知道子类是怎么启动引擎的,所以声明成抽象方法,由子类去实现,每个子类知道它自己应该怎么启动引擎。这时你会问,直接在子类写启动引擎方法就行了,为什么还要在父类写个抽象方法?答:为了实现扩展,示例如下:

    static class 驾驶员 {
        public void 开车(交通工具 vehicle) {
            vehicle.启动引擎();
        }
    }
这里,我们的驾驶员开车的方法中,参数类型为交通工具,你即可以传摩托车,也可以传汽车,因为交通工具上定义有抽象方法“启动引擎()”,所以可以直接调用这个方法,不需要强转,否则你还要写代码判断这个交通工具是摩托车,则强转为摩托车,然后调用摩托车的启动引擎()方法,如果是汽车,则强转为汽车,然后再调用汽车的启动引擎()方法,如果以后再来10种交通工具呢?你要写10个判断,10个强转代码,是不是很累啊,这样的代码我们称之为扩展困难。但是如果父类上抽象方法的定义,则可以不用强转,直接调用,一行代码搞定,随便你来多少交通工具都不用变了,这样的代码,我们称之为容易扩展。 如果我的回答帮助到了你,麻烦结贴给点积分,谢谢^_^
象话 2020-04-21
  • 打赏
  • 举报
回复
有了抽象,就有了多态;有了抽象,就有了继承;封装、继承、多态,其实都依赖于抽象;
kse_music 2020-04-20
  • 打赏
  • 举报
回复
抽象类其实就是提取子类的共同特征的可以约束属性和行为
cfbs168 2020-04-19
  • 打赏
  • 举报
回复
引用 5 楼 paullbm 的回复:
首先需要说明的是:
抽象类里必须含有抽象方法吗 ?答:非必须
但如果定义了抽象类没有抽象方法,何必定义这个类为抽象类?
如果定义的抽象类里全是抽象方法,那为何不改成定义为一个接口?

===================
为什么要有抽象类呢? 抽象类中如果没有抽象方法是不是就没有意义?如果是,为什么没有意义呢?
抽象方法存在的意义又是什么呢?
-------------
1. 如果抽象类中没有抽象方法,不如直接定义一个实体类。因为实体类可以通过new的方式创建实例,而抽象类不能。当你想利用这个抽象类的时候,还得写一个子类实现类,那纯粹增加代码冗余度和增加维护成本了(如果项目比较大,类似情况多的话)
2.抽象类往往用于存在于继承关系中,抽象类中的非抽象方法等于是为所有子孙类制定了统一标准!虽然在一定程度上接口似乎也能如此,但接口往往是制定的一个行业标准,而遵循这种标准的实现类之间的关系往往是平等的,不存在父子关系!

打个简单的比方:
想一想爷爷-父亲-孙子的关系,(比如涉及到遗产继承的问题,很明显的是继承关系)
再想一想生产一台笔记本电脑的各个厂商的关系!(厂商只是遵循制定笔记本电脑的标准来生产笔记本电脑,很明显厂商之间是平等的,甚至是独立且相互透明的)

楼上这位老师可能还没有真正明白抽象类的意义和面向抽象编程的意义。
为什么要有抽象类呢? 抽象类中如果没有抽象方法是不是就没有意义?如果是,为什么没有意义呢?
我也来回答一下你这个问题:
抽象思维是我们理工人士必须要熟练掌握并应用的思维方式,抽象类是把多个类共通的部分进一步抽象出来,以抽象类的形式表明这是规范和标准,即使其没有抽象方法,依然标明这些成员是规范和标准,所以抽象类不能创建对象(即使没有抽象方法),抽象类定义的成员变量和方法标明其子类必须具有这些成员变量和该方法,那么抽象类的多个子类可以继承这些方法,也可以重写父类的方法。当然子类也可以新增成员变量和方法。所以 抽象类中如果没有抽象方法是也是有意义的。
SilentHunter460 2020-04-17
  • 打赏
  • 举报
回复
引用 8 楼 正怒月神 的回复:
为什么要有抽象类? 这个问题不难回答,抽象类最特殊的地方,在于可能有抽象方法。 抽象方法也是抽象类和普通类的最大区别。(所以这也导致抽象类无法实例化) 抽象方法可以不用实现。 这里说一个题外话,抽象类是接口的特殊实现方式。 这就像说为什么要有接口? 其实很简单,我知道这个类必须有这个功能,但是我不知道派生类是如何具体实现的。 比如说,抽象类鸟,派生类,老鹰和企鹅。 同样是翅膀,一个用来飞,一个用来游泳。 还是这句话我知道这个类必须有这个功能,但是我不知道派生类是如何具体实现的。
学了一段时间java,开始我也不理解抽象类意义,现在慢慢理解了一点。继续补充你的故事,看看我说得对不对。 其实不要抽象类鸟也是可以的,但你就千万记得给老鹰类、企鹅、鸡、鸭、鹅都加上翅膀,否则会生出一堆没翅膀的畸形。 如果有抽象类鸟和翅膀方法,你就无论如何也不会忘记给老鹰类、企鹅、鸡、鸭、鹅加上翅膀,因为eclipse会给你划上一堆红线,不解决这些红线你的程序都跑不起来。
to_keep_moving 2020-04-14
  • 打赏
  • 举报
回复
抽象类还有一个用法,我补充一下,你老大定义了一个抽象类,让你去继承这个类,就必须实现它定义的抽象类中抽象方法的名字,老大啪啪啪定义了是个抽象方法,将名字确定了,你只负责实现具体的代码就行了。
maradona1984 2020-04-14
  • 打赏
  • 举报
回复
没有抽象方法的抽象类,你可以觉得他没有意义,但实际上还是有有意义的,比如这个类只能被继承使用
qq_39936465 2020-04-14
  • 打赏
  • 举报
回复
引用 楼主 一只223317 的回复:
为什么要有抽象类呢? 抽象类中如果没有抽象方法是不是就没有意义?如果是,为什么没有意义呢? 抽象方法存在的意义又是什么呢?
抽象类介于普通类和接口之间,是一种补充。你可以理解为普通类是所以子类的共性,而接口是所有子类的差异规范化,而抽象类是既含有共性又含有差异规范化。抽象类是为了编程更灵活,减少重复代码。
正怒月神 2020-04-09
  • 打赏
  • 举报
回复
为什么要有抽象类? 这个问题不难回答,抽象类最特殊的地方,在于可能有抽象方法。 抽象方法也是抽象类和普通类的最大区别。(所以这也导致抽象类无法实例化) 抽象方法可以不用实现。 这里说一个题外话,抽象类是接口的特殊实现方式。 这就像说为什么要有接口? 其实很简单,我知道这个类必须有这个功能,但是我不知道派生类是如何具体实现的。 比如说,抽象类鸟,派生类,老鹰和企鹅。 同样是翅膀,一个用来飞,一个用来游泳。 还是这句话我知道这个类必须有这个功能,但是我不知道派生类是如何具体实现的。
nayi_224 2020-04-09
  • 打赏
  • 举报
回复
抽象类的特征就是抽象方法,我使用抽象类的原因只是想告诉自己这个类必须重新创建并且提醒自己有些方法必须去实现,而这时不用接口的原因就是我依然需要这个抽象类提供的一些实体方法。
小灰狼 2020-04-09
  • 打赏
  • 举报
回复
抽象类的方法是由子类实现的,任何一个抽象类的对象,一定是其实现了所有抽象方法的子类的对象,通过类型向上转型得到的 楼上版主说得很对,因为抽象类可以肯定一定会有这个方法,但是如何实现这个方法,在抽象的类型层面还无法确定,只有到更精确的子类才能确定如何实现。 比如一个抽象类员工(Employee),它一定有一个开始工作方法(work()) 但是员工有很多工种,有会计、产品经理、清洁工、保安、司机……,每个工种会有他们工作的内容,因此 work 方法必须到子类才能知道如何实现。 为什么要在父类定义抽象方法? 因为很多时候,只关心父类型,不必关注子类型。 比如老板叫大家开大会,开完会之后说:大家回去工作吧? 如果没有抽象父类,你就必须一个工种一个工种地调用:会计同事们,你们回去算账吧、保安同事们,你们去巡逻吧、产品经理们,你们去了解客户需求吧……
Little5 2020-04-08
  • 打赏
  • 举报
回复
一个最简单的栗子: 人类就是男人和女人的抽象类 人类有共同的方法,工作。 但是具体到每个人,工作的内容肯定是不一样的,所以这个必须由子类自己来实现,抽象类只是表明这一类都具有的共同方法。 用抽象类其实主要是为了多态和后期绑定,也可以理解为运行时绑定。如果按照你说的直接用子类。那就属于编译时绑定。这样不利于维护和扩展。 举个栗子: 工作肯定都是人类做。不管男女。所以doWork方法就需要传递一个Person对象进来:

public class Test
{

	public static void main(String[] args)
	{
		doWork(new Male());
	}

	public static void doWork(Person p)
	{
		p.work();
	}

}

abstract class Person
{
	abstract void work();
}

class Male extends Person
{
	@Override
	void work()
	{
		System.out.println("Male work");
	}
}

class Female extends Person
{
	@Override
	void work()
	{
		System.out.println("Female work");
	}
}
如果按照你的逻辑。不用抽象类。直接传递子类对象。那doWork方法就应该声明成这样:

	public static void doWork(Male male)
	{
		male.work();
	}
这样肯定是没问题的。但是如果以后要修改呢?这个工作要改成女人来做呢?那你又只有重新声明一个方法,参数是女人对象?那如果以后要人妖来工作呢? 你是不是还要声明一个人妖的方法?这样就很繁琐,而且不利于维护。 而我们用抽象类就不一样了。子类都去实现人类的work方法,因为每个人的工作内容不同,所以每个子类的方法内容都不尽相同。写代码的时候我们也不管谁来工作,反正只需要知道传递一个人类对象进去,方法体里被抽象成了一个人类对象来工作。然后调用work方法就是了。到了运行的时候编译器才知道到底哪个对象来工作,这就是运行时绑定。比如:

	public static void main(String[] args)
	{
		doWork(new Male());
	}

	public static void doWork(Person p)
	{
		p.work(); // 方法里不管男女,只要是个人就行
	}
是不是很简单了?如果我要维护,我只需要doWork(传递不同对象进去);然后doWork的内容就不同了。这就是多态。 这是抽象编程很典型的一个例子。先抽象后具体。编码前期,我们其实不能确定业务逻辑的具体执行对象。所以我们把具有共同特征的一类抽象出来,用抽象类代替具体类。到后期,需要执行业务逻辑的时候,再传入具体的对象(这里涉及到向上转型)。根据传入的对象不同,业务逻辑的处理也不同。就形成了多态。 你自己体会一下用抽象类的好处。
paullbm 2020-04-08
  • 打赏
  • 举报
回复
首先需要说明的是: 抽象类里必须含有抽象方法吗 ?答:非必须 但如果定义了抽象类没有抽象方法,何必定义这个类为抽象类? 如果定义的抽象类里全是抽象方法,那为何不改成定义为一个接口? =================== 为什么要有抽象类呢? 抽象类中如果没有抽象方法是不是就没有意义?如果是,为什么没有意义呢? 抽象方法存在的意义又是什么呢? ------------- 1. 如果抽象类中没有抽象方法,不如直接定义一个实体类。因为实体类可以通过new的方式创建实例,而抽象类不能。当你想利用这个抽象类的时候,还得写一个子类实现类,那纯粹增加代码冗余度和增加维护成本了(如果项目比较大,类似情况多的话) 2.抽象类往往用于存在于继承关系中,抽象类中的非抽象方法等于是为所有子孙类制定了统一标准!虽然在一定程度上接口似乎也能如此,但接口往往是制定的一个行业标准,而遵循这种标准的实现类之间的关系往往是平等的,不存在父子关系! 打个简单的比方: 想一想爷爷-父亲-孙子的关系,(比如涉及到遗产继承的问题,很明显的是继承关系) 再想一想生产一台笔记本电脑的各个厂商的关系!(厂商只是遵循制定笔记本电脑的标准来生产笔记本电脑,很明显厂商之间是平等的,甚至是独立且相互透明的)
qybao 2020-04-06
  • 打赏
  • 举报
回复
引用 2 楼 一只223317 的回复:
可是抽象方法不是只声明了吗,所有的实现都是在子类中,那这样修改的话还是要在每一个子类中去修改,因为父类里的抽象方法不是连方法体都没有吗

你说的是修改具体业务的代码,那确实是必须改子类重写的方法,但是你有没有想过修改共通部分呢?
比如上面的例子,我希望所有的子类在doSpecial之前加一个处理,你是去修改每个doSpecia,在方法l刚开始的时候加一段代码,还是只需要修改抽象类的doAll方法就好了呢(在调用deSpecial前加一段代码)?
一只红烧虾 2020-04-06
  • 打赏
  • 举报
回复
引用 1 楼 qybao的回复:
如果不同子类有相同的处理,那是不是把相同的处理抽出来统一管理,不同的地方用抽象方法让子类去实现,这样是不是更高效?将来如果相同处理的地方发生改变,只要改一个地方就可以了,不用修改各个子类。
比如
abstract class AC {
public void doAll() {
for (int i = 0; i < 3; i++) {
doCommon(i + 1); //抽象类负责共通部分
}
doSpecial(); //子类负责特殊部分
for (int i = 3; i < 6; i++) {
doCommon(i + 1); //抽象类负责共通部分
}
}

private void doCommon(int i) {
System.out.println("do common " + i); //共通处理部分,将来共通处理也修改,只需要改一个类
}

abstract protected void doSpecial();
}

class SA extends AC {
protected void doSpecial() {
System.out.println("do sa special operation");
}
}

class SB extends AC {
protected void doSpecial() {
System.out.println("do sb special operation");
}
}

public class Sample {
public static void main(String[] args) {
SA sa = new SA();
SB sb = new SB();
sa.doAll();//如果没有抽象类,子类都要写抽象类的共通处理的部分,代码冗余
sb.doAll();//而且万一有人写代码失误,共通处理的部分被改写了,不能保证共通处理的整合统一性
}
}


抽象类没有抽象方法也可以,只是这样的话就没必要定义成抽象类了,定义成普通类就可以。
抽象类只是抽象了子类的共通,并不具体化,也可以说是不实现具体处理业务,只是负责调度业务,具体业务留给子类去实现。因为抽象类是抽像的,不具体,不完整,所以不想让用户直接实例化,用户想实例化就要重写抽象方法实现具体业务,所以就要用抽象方法来限制用户不正确使用。
可是抽象方法不是只声明了吗,所有的实现都是在子类中,那这样修改的话还是要在每一个子类中去修改,因为父类里的抽象方法不是连方法体都没有吗
qybao 2020-04-06
  • 打赏
  • 举报
回复
如果不同子类有相同的处理,那是不是把相同的处理抽出来统一管理,不同的地方用抽象方法让子类去实现,这样是不是更高效?将来如果相同处理的地方发生改变,只要改一个地方就可以了,不用修改各个子类。
比如
abstract class AC {
public void doAll() {
for (int i = 0; i < 3; i++) {
doCommon(i + 1); //抽象类负责共通部分
}
doSpecial(); //子类负责特殊部分
for (int i = 3; i < 6; i++) {
doCommon(i + 1); //抽象类负责共通部分
}
}

private void doCommon(int i) {
System.out.println("do common " + i); //共通处理部分,将来共通处理也修改,只需要改一个类
}

abstract protected void doSpecial();
}

class SA extends AC {
protected void doSpecial() {
System.out.println("do sa special operation");
}
}

class SB extends AC {
protected void doSpecial() {
System.out.println("do sb special operation");
}
}

public class Sample {
public static void main(String[] args) {
SA sa = new SA();
SB sb = new SB();
sa.doAll();//如果没有抽象类,子类都要写抽象类的共通处理的部分,代码冗余
sb.doAll();//而且万一有人写代码失误,共通处理的部分被改写了,不能保证共通处理的整合统一性
}
}


抽象类没有抽象方法也可以,只是这样的话就没必要定义成抽象类了,定义成普通类就可以。
抽象类只是抽象了子类的共通,并不具体化,也可以说是不实现具体处理业务,只是负责调度业务,具体业务留给子类去实现。因为抽象类是抽像的,不具体,不完整,所以不想让用户直接实例化,用户想实例化就要重写抽象方法实现具体业务,所以就要用抽象方法来限制用户不正确使用。

62,625

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧