感慨一下,到了现在感觉Java里面很多东西都是模模糊糊,不能这样了,一点点解决吧。今天看了继承与多态的一些内容,感觉看得很浅,先写下来,算是巩固,如果后面看到更好的内容,再慢慢加上去。

继承与多态,他们是面向对象里圈里面的两个好朋友呀。我想,这一部分的内容应该是最常用也是最常见的了吧。

继承是什么

说到继承,我最先想到的是可以避免代码重复,也就是代码复用。其实,除了这个作用之外,继承还给我们提供了一个强大的武器“多态”,但是我以前却常常忽略它,真是不好意思啊。

举例子吧,有两个类:SamsungBrand,AppleBrand,这是两个品牌,那么对于一个品牌,我们可能想知道它是什么时候创立的,他的名称是什么,所以可以在这两个类中分别设立两个变量,一个是年份(String year),另一个是名称(String brand),然后显然要为这两个变量设置set和get方法。代码很简单,我就不贴了,可以想象的到,两个类中都有year和brand。嗯,这样看起来也不是很麻烦,但是如果要写100个品牌的话,那就非常累了。

所以我们可以提取这些类的公共点,然后放在一个Brand类中,并且让具体的品牌去继承这个Brand就大大的减少了代码的冗余。

所以,记住一句话:继承的是共同的行为

那么,下面我们来就来看看多态吧,这是很重要的。前面已经说到,一个类A可以继承另一个类B(通过extends关键字),那么A是子类,B是父类。子类和父类的关系我们可以说成“是一个”(is-a)。

比如前面的例子:SamsungBrand和AppleBrand都是Brand的子类,那么它们的关系就是:

SamsungBrand is a Brand,AppleBrand is a Brand。

这个很重要。

所以说,如果我们这样写代码:

Brand samsung = new SamsungBrand();//从左往右,符合is-a
Brand apple = new AppleBrand();

显然这是符合is-a的,所以编译器说,你可以通过。

但是,如果我们这样写:

SamsungBrand samsung = new Brand();//我一定会是samsung吗?
AppleBrand apple = new Brand();//我一定会是apple吗?

一个Brand对象可能是Samsung的,也可能是Apple的,所以编译器是不会让这样的代码通过的。

但此时,会有一个问题:

Brand brand = new SamsungBrand();
SamsungBrand samsung = brand;

代码显然是不给编译通过的,编译器查到brand是Brand类型的,那么brand不一定是Samsung的,所以不会让着两行代码编译通过。但是作为代码的编写者,我很清楚的知道,这个brand就是samsung,那么有什么办法让编译器闭嘴呢?

Java提供了一种方法:扮演(Cast),让brand扮演SamsungBrand类型的对象,告诉编译器不要啰嗦。

Brand brand = new SamsungBrand();
SamsungBrand samsung = (SamsungBrand)brand;

这样的话,着两行代码就会编译通过。但是要注意,如果让对象“扮演”了,就意味着,后果自负!

想想看,如果把第一行代码改成new AppleBrand(),但是下面一行代码不变,因为用了“扮演”,编译器不会再啰嗦,可是,在运行的时候,哇,出错了!JVM抛出了ClassCastException异常。

Exception in thread "main" java.lang.ClassCastException: AppleBrand cannot be cast to SamsungBrand

有了上面的知识储备,相信下面讲起来会轻松一点。对了,上面的内容不是废话!is-a懂了很重要,Cast也很重要,懂了这些可以让你写的代码更加灵活并且易于维护。

真的吗?我们来看一下:设计一个static方法,这个方法传入某一个品牌的对象,然后输出品牌的诞生的年份和名称。

public static void show(SamsungBrand brand){
System.out.println(brand.getYear()+","+brand.getName());
}
public static void show(AppleBrand brand){
System.out.println(brand.getYear()+","+brand.getName());
}

上面是一种不错的解决方法,但是当有更多的品牌的时候,也许就不会觉得这样写好了。

这个时候,我们可以这样写:

public static void show(Brand brand){
System.out.println(brand.getYear()+","+brand.getName());
}

然后分别传入两种品牌的对象,依然会正确!这是为什么?

答案就是:方便的不得了的 “多态” 帮了大忙!

当传进一个AppleBrand对象的时候,实际上brand只是挂着Brand的牌子,实际上做的是AppleBrand的工作,调用getYear()实际上是调用AppleBrand中的getYear()。

还有一个小内容,我在用eclipse编写继承代码的时候,有时候重写(override)某个方法是,IDE会自动在这个方法的前面加上一个@Override,然后我把它删了,代码依然正常。那这个代码还有啥用呢?

其实吧,这个小东西还确实挺有用的(JDK5之后出现的,话说回来,没用人家还不早删了)!

加入说新增加一个方法:show(),用来显示品牌信息。在Brand中,show()设定为空方法,后面继承的时候,如果不小心,将show写成了Show,额..结果可想而知了哈。

为了避免这种错误呢,可以让我们亲爱的编译器在编译的时候帮我们检查一下,这个是不是override,那怎么告诉编译器要不要检查呢?

哈,就是@Override!!!

下面再说一下抽象方法和抽象类

刚刚说到了show()是一个空方法,由子类去实现,假设是在一个很大的部门开发,一个人开发Brand,剩下n个人开发其子类,很有可能其中会有朋友忘记实现show()这个方法。如果要一个个去通知,会很痛苦的(打电话不接,发短信不会,啊啊啊啊)。该怎么办呢?

抽象方法就是用来决绝这个问题的:使用abstract(小写的哦!!)关键字表示该方法为抽象方法,这个方法不必写{}块,直接用“;”结束就行了!

比如:

public abstract void show();

这样定义之后,子类如果不去实现这个方法,会报错的,哈哈,方便!(额,不全面,实际上作为子类有两种选择:1.乖乖实现;2.继续把它声明为abstract

如果一个类中,有抽象方法,那么:该类一定要也声明为抽象类。

并且,抽象类是不能实例化的!(new)

这是因为抽象类是一个为完成(实现)的类。

还有两点就是:虽然抽象方法可能没有完成,但是可以使用;虽然抽象类不可以实例化,但是可以声明!

继承进阶

“进阶”看上去就高端大气上档次。其实没有这么夸张,仅仅是将一些易错的内容放进来。

内容1:

内容2:

构造函数是最常见的了:如果我们在类中啥都不定义,那么系统会为我们定义一个无参的默认构造函数;但是如果我们在类中定义了任何一种构造函数,系统将不再为我们构造默认构造函数。

加入了继承的概念后,我们要记住一点,如果子类构造函数中没有指定执行父类中那个构造函数,默认会调用父类中无参构造函数,也就是说:

class Some{
Some(){
System.out.println("this is some");
}
}
class Other extends Some{
Other(){
System.out.println("this is other");
}
}
//上面的代码等价于
class Some{
Some(){
System.out.println("this is some");
}
}
class Other extends Some{
Other(){
super();
System.out.println("this is other");
}
}

从这个代码也可以看出,如果定义了一个Other对象,实际上还是先执行Other(),但是呢,在第一步执行了super(),调用了父类的无参构造函数。

可以在子类的构造函数中,利用super,调用父类指定的构造函数(有参无参随便你),但是,记住一定要放在第一句!!!!

内容3:

下面来看一下final,这个东西类似于C++中的const,定义之后不可以改变变量的值,可以先声明后赋值。

可以将这个final放在方法前,也可以放在类前,它的作用,该方法/类,不可以再被重写/继承。

经常会看到final和static连在一起使用,一开始不能理解,现在似乎有一点明白了:我们在设计类的时候,可能经常会用到一些常量,假设用到了一个对象p,我们可以用final将其定义为常量,那么在类实例化之后,这个就不会再改变(是我们想要的结果),但是同时也有一个问题,每实例话一次,可能都要为这个p分配空间,而实际上,我们只需要一个p就足够了,不必浪费内存。要解决这个问题,只需要将final和static连起来用就可以啦。

额…写的累死,这一部分内容就先到这里了。

Java继承与多态的更多相关文章

  1. Java 继承和多态

                                                        Java  继承和多态 Java 继承 继承的概念 继承是java面向对象编程技术的一块基石,因 ...

  2. Java继承和多态实例

    我们知道面向对象的三大特性是封装.继承和多态.然而我们有时候总是搞不清楚这些概念.下面对这些概念进行整理, 为以后面向抽象的编程打下坚实的基础. 封装的概念还是很容易理解的.如果你会定义类,那么相信你 ...

  3. Java 继承、多态与类的复用

    摘要: 本文结合Java的类的复用对面向对象两大特征继承和多态进行了全面的介绍. 首先,我们介绍了继承的实质和意义,并探讨了继承,组合和代理在类的复用方面的异同.紧接着,我们依据继承引入了多态.介绍了 ...

  4. Java继承,多态,组合应用

    继承:  面向对象的三大特征之一:    是类和类之间的一种拓展关系,是一种从一般到特殊的关系;    格式: sub   extends Super,  我们把sub称为子类或者拓展类, 把supe ...

  5. java继承和多态

    父类和子类 如果类C1扩展自另一个类C2,那么C1称为子类或派生类,C2称为父类或基类.派生类可以从它的基类中继承可访问的数据域和方法,还可添加新数据域和新方法 例如:实现一个几何图形基类; clas ...

  6. 四. Java继承和多态8.Java final关键字:阻止继承和多态

    在 Java 中,声明类.变量和方法时,可使用关键字 final 来修饰.final 所修饰的数据具有“终态”的特征,表示“最终的”意思.具体规定如下: final 修饰的类不能被继承. final ...

  7. 四. Java继承和多态4. 多态和动态绑定

    在Java中,父类的变量可以引用父类的实例,也可以引用子类的实例. 请读者先看一段代码: public class Demo { public static void main(String[] ar ...

  8. java继承和多态举例

    public class Test1 { public static void main(String[] args) { System.out.println(new Dog().name);//狗 ...

  9. Java继承与多态浅析

    一.继承 1.通过extends继承的父类可以是不加abstract关键字的普通类,也可以是加了abstract关键字的抽象类.继承普通类时可以覆写父类的方法,或者创建自己独有的方法,或者这两     ...

随机推荐

  1. [shiro学习笔记]第二节 shiro与web融合实现一个简单的授权认证

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39933993 shiro官网:http://shiro.apache.org/ shi ...

  2. Android 之Toast讲解-android学习之旅(一)

    Toast比较常用,用于显示简短的提醒,比如网络连接断开等. Toast的简单编码实例 findViewById(R.id.button1).setOnClickListener(new OnClic ...

  3. 利用Camera和Matrix实现有趣的卡片效果

    这篇文章主要讲解一个翻转切换内容的卡片效果,主要利用Camera和Matrix来实现,主要是为了加深对Camera和Matrix的理解,如果对Camera和Matrix不清楚地童鞋可以看我的上篇文章: ...

  4. MyBatis Generator For Eclipse 插件安装

    由于在ORM框架MyBatis中,实现数据表于JavaBean映射时,配置的代码比较的复杂,所以为了加快开发的效率,MyBatis官方提供了一个Eclipse的插件, 我izuoyongjiushis ...

  5. 安卓仿QQ红包领取详情界面动画

    为了能清楚的看到这个效果,本人不惜几次花费重金给众群叼发放红包,来查看红包领取详情界面的动画效果,QQ效果如图: 图中我们可以看到,动画处的头像和文字是一起的,即同时并且是整体,注意,是整体进行缩放的 ...

  6. 03_NoSQL数据库之Redis数据库:list类型

     lists类型及操作 List是一个链表结构,主要功能室push,pop.获取一个范围的所有值等等,操作中key理解为链表的名字.Redis的list类型其实就是一个每个元素都是string类型 ...

  7. Ubuntu15.10下如何使用EasyGui模块开发Python GUI

    偶然的一个机会,发现了github上的这个开源的项目,easygui for python(一个基于TKinter的模块) 感觉很是惊讶,原来python也可以这么简单的开发出一些GUI界面(究其原因 ...

  8. 最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  9. MOAC中“MO:安全性配置文件“对于开发者

    1. 获取配置文件的值:应用开发员->配置文件->输入用户配置文件名,找到上面的名称,即可填入fnd_profile.VALUE()中. 2. MO:安全性配置文件有值的话,就代表启用了M ...

  10. Cocos2D:塔防游戏制作之旅(十四)

    塔之战:炮塔的攻击 炮塔就位了?检查.敌人前进中?再次检查 - 它们看起来就是如此!看起来到了击溃这些家伙的时候了!这里我们将智能置入炮塔的代码中去. 每一个炮塔检查是否有敌人在其攻击范围.(炮塔一次 ...