java基础——面向对象(二)
来源:互联网 发布:php为什么比aps.net好 编辑:程序博客网 时间:2024/06/07 18:48
第三讲 继承
一、概念
多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可
多个类可以称之为子类,单独这个类称为父类,或超类
子类可以直接访问父类中非私有的属性和行为
extends关键字
通过extends关键字让类与类之间产生继承关系
继承的出现,提高了代码的复用性,继承的出现让类与类之间产生了关系,提供了多态的前提
注意:子类不可以具有父类中私有的内容
父类是怎么来的呢?是向上不断抽取而来的
什么时候定义继承呢?
必须保证类与类之间有所属,即:xxx是zzz中的一类
特点:
java允许单继承,不直接支持多继承,将多继承进行其他方式的体现
单继承:一个子类只能继承一个父类
多继承:一个子类可以有多个父类,但是多继承调用可能出现不确定性,所以java保留了多继承的好处,改良了它弊端,用多实现来体现
java还支持多重继承
class A{}
class B{} extends A
class C{} extends B
形成继承体系
学习继承体系是,应该参阅顶层类中的内容
了解这个体系的基本功能
使用这个体系的基本功能,需要创建最子类的对象
二、继承出现后,在代码中的体现
重点在于成员的体现
1、成员变量
特殊情况:子父类中定义了一摸一样的成员变量,都存在于子类对象中
如何在子类中直接访问同名父类中的变量呢?通过关键字super来完成
super和this很像
this:代表的是本类的对象的引用。
super:代表的是父类的内存空间。
注意:这种情况开发见不到,因为父类一旦描述完了属性,子类直接使用就可以了。
2、成员函数
【子父类中成员函数的特点】
特殊情况:
子父类中的定义了一模一样的函数。
运行的结果:子类的函数在运行。
这种情况在子父类中,是函数的另一个特性:override(重写,覆盖,复写)
随着电话的升级,只显示号码不爽,希望显示姓名,大头贴。
修改源码,虽然费劲但是可以解决,不利于后期的维护和扩展。
为了扩展方便。新功能是不是新的电话具备呢?
单独描述单独封装。新电话也是电话中的一种。继承。直接获取父类中的功能。
但是新电话的来显功能已经变化了。需要重新定义。
那么定义一个新功能合适吗?比如newShow,不合适,因为父类已经将来显功能定义完了,
子类完全不需要重新定义新功能。直接用就可以了。如果子类的来显功能内容不同。
直需要保留来显功能,定义子类的内容即可:这就是重写的应用!
【重写(覆盖)的注意事项】
1,子类覆盖父类,必须保证全要大于或者等于父类的权限。
Fu:
private void show(){}
Zi:
public void show(){}
2,静态覆盖静态。
写法上稍微注意:必须一模一样:函数的返回值类型函数名参数列表都要一样。
【总结】
当一个类是另一个类中的一种时,可以通过继承,来扩展功能。
如果从父类具备的功能内容需要子类特殊定义时,使用重写。
3、构造函数
【子父类中构造函数的特点】
当子父类都有构造函数时,发现结果为:
fu constructor run
zi constructor run
先执行了父类的构造函数,再执行子类的构造函数。
【这是为啥呢?】
因为子类的所有的构造函数中的第一行都有一句隐式语句super(); //默认调用的是父类中的空参数的构造函数。
【子类中的构造函数为什么有一句隐式的super()呢?】
原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。
才可以更方便的使用父类中的内容。
【小结】
当父类中没有空参数构造函数时,子类的构造函数必须同构显示的super语句指定要访问的父类中的构造函数。
这就是传说中的子类实例化过程。
【实例化过程的细节】
1,如果子类的构造函数第一行写了this调用了本类其他构造函数,那么super调用父类的语句还有吗?
没有的,因为this()或者super(),只能定义在构造函数的第一行,因为初始化动作要先执行。
2,父类构造函数中是否有隐式的super呢?
也是有的。记住:只要是构造函数默认第一行都是super();
父类的父类是谁呢?super调用的到底是谁的构造函数呢?
Java体系在设计,定义了一个所有对象的父类Object,
【总结】
类中的构造函数默认第一行都有隐式的super()语句,在访问父类中的构造函数。
所以父类的构造函数既可以给自己的对象初始化,也可以给自己的子类对象初始化。
如果默认的隐式super语句没有对应的构造函数,必须在构造函数中通过this或者super的形式明确调用的构造函数。
【问题】
1,this语句和super语句是否可以在同一个构造函数中出现呢?不行,因为必须定义在第一行。
2,为什么要定义在第一行呢?因为初始化动作要先执行。
细节:
1、如果子类的构造函数第一行写了this调用了本类其他构造函数,那么super调用父类的语句还有吗?
没有了,因为this()或super()只能定义在构造函数的第一行,因为初始化动作要先执行
2、父类构造函数中是否有隐式super呢?
有的,只要是构造函数,默认第一行都是super;父类的父类是谁呢?super调用的到底是谁的构造函数呢?
java体系在设计时,定义了一个所有对象的父类Object
总结:
类中的构造函数默认第一行都有隐式super语句,在访问父类的构造函数
所以,父类的构造函数既可以给自己的对象初始化,也可以给子类的对象进行初始化
如果默认的隐式super的语句没有对应的构造函数,必须在构造函数中通过this或者super的形式明确调用的构造函数
子类实例化过程的应用。也是super调用的应用
什么时候用super调用父类中的构造函数呢。只要使用父类的指定初始化动作,就在子类中通过super(参数列表)格式进行调用
final关键字
继承的弊端:破坏了封装性(重写)
不让其他类继承该类,就不会重写
可以通过java中的一个关键字final来实现,final是一个修饰符,可以修饰类,方法,变量(成员变量,局部变量,静态变量)
特点:
1、final修饰的类是一个最终类,不能派生子类,如果类中出现部分可以重写,部分不可以重写怎么办?
只要让制定的方法最终化即可
2、final修饰的方法是最终方法,不可以重写
3、final修饰的变量时一个常量,只能被赋值一次
什么时候会在程序中定义final常量呢?
当程序中一个数据使用时是固定不变的,这时为了增加阅读性,可以给该数据起个名字,这就是变量,为了保证这个变量的值不被修改,加上final修饰,这就是一个阅读性很强的常量
抽象类概述
定义:抽象就是从多个事物中将共性的,本质的内容抽取出来
例如:狼和狗都属于犬科,犬科就是抽象出来的概念
抽象类:
java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含该方法的类就称为抽象类
抽象类的特点:
抽象类和抽象方法必须用abstract关键字来修饰
抽象方法只有方法声明,没有方法主体,定义在抽象类中
格式:修饰符abstract返回值类型函数名(参数列表);
抽象函数:需要abstract修饰,并“;”结束
抽象类不可以被实例化,也就是不可以用new创建对象
原因如下:
1、抽象类是具体事物抽取出来的,本身不是具体的,没有对应的实例
2、而且抽象类即使创建了对象,调用抽象方法也没有意义
抽象类通过其子类实例化,而子类需要覆盖抽象类中所有抽象方法后才可以创建对象,否则该子类也是抽象类
之所以继承,更多的是思想,是面对共性类型操作会更简单
细节:
1、抽象类是一个父类,因为抽象类是不断向上抽取而成
2、抽象类是否有构造函数?
有的,因为虽然不能给自己初始化,但是可以给子类初始化
抽象类和一般类的异同点:
相同:a、他们都是用来描述事物的。b、都可以定义属性和行为
不同:a、一般类可以具体的描述事物,抽象类描述事物的信息不具体
b、抽象类可以多定义一个成员,抽象函数
c、一般类可以创建对象,而抽象类不可以创建对象,必须通过子类来完成
3、抽象类中是否可以不定义抽象方法?
可以的,那这个抽象类的存在有何意义?仅仅是不让该类创建对象
4、抽象关键字abstract不可以和以下关键字共存
a、final//final修饰的类不可以派生子类,而抽象类必须有子类
b、private//抽象方法必须被覆盖,加上private后就无法被覆盖
c、static//静态可以被类名调用,但是抽象类被类名调用无意义
interface(接口)关键字
抽象类中可以定义抽象方法的
当一个抽象类中的方法全是抽象的
这时,可以通过另一种特殊的形式类实现——接口
接口中的成员已经被限定为固定的几种
接口的定义格式先介绍两种:
1、定义变量;但是变量必须有固定的修饰符修饰:public static final,所以接口中的变量也称为常量
2、定义方法;方法也有固定的修饰符:public abstract,接口中的成员都是公共的
接口的特点:
1、接口不可创建对象
2、子类必须覆盖掉接口中所有抽象方法后,子类才可以实例化,否则子类就是一个抽象类
接口最重要的体现
解决多继承的弊端,将多继承这种机制在java中通过多实现完成了
第四讲 多态
【体现】
父类的引用或者接口的引用指向了自己的子类对象。
Dogd = new Dog();//Dog对象的类型是Dog类型。
Animala = new Dog();//Dog对象的类型右边是Dog类型,左边Animal类型。
【好处】
提高了程序的扩展性。
【弊端】
通过父类引用操作子类对象时,只能使用父类中已有的方法,不能操作子类特有的方法。
【前提】
1,必须有关系:继承,实现。
2,通常都有重写操作。
【子类的特有方法如何调用呢?】
Animala = new Dog();//Animal是父类型,new Dog()是子对象。
但是父类型引用指向子类对象时,这就是让子类对象进行了类型的提升(向上转型)。
向上转型好处:提高了扩展性,隐藏了子类型。弊端:不能使用子类型的特有方法。
如果要想使用子类的特有方法,只有子类型可以用。
可以向下转型,强制转换。
Animala = new Dog();
a.eat();
Dog d= (Dog)a;//将a转型为Dog类型。向下转型。
d.lookHome();
向下转型什么时候用?当需要使用子类型的特有内容时。
注意:无论向上还是向下转型,最终都是子类对象做着类型的变化。
【向下转型的注意事项】
Animala = new Dog();
//Catc = (Cat)a;向下转型因为不明确具体子类对象类型,所以容易引发ClassCastException异常。
所以为了避免这个问题,需要在向下转型前,做类型的判断。
判断类型用的是关键字instanceof
多态中,成员调用的特点。
1,成员变量。
当子父类中出现同名的成员变量时。
多态调用该变量时:
编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。
运行时期:也是调用引用型变量所属的类中的成员变量。
简单记:编译和运行都参考等号的左边。
编译运行看左边。
2,成员函数。
编译,参考左边,如果没有,编译失败。
运行,参考右边的对象所属的类。
编译看左边,运行看右边。
对于成员函数是动态绑定到对象上。
3,静态函数。
编译和运行都参考左边。
静态函数是静态的绑定到类上。
【结论】
对于成员变量和静态函数,编译和运行都看左边。
对于成员函数,编译看左边,运行看右边。
内部类
当A类中的内容要被B类访问,而A类还需要创建B类对象,访问B类内容时,可将B类定义到A类内部,这样访问更为便捷,将B类称为内部类
访问方式:
内部类可以直接访问外部类中的所有成员,包含私有的。
而外部类要想访问内部类中的成员,必须创建内部类的对象。
当描述事物时,事物的内部还有事物,这个内部的事物还在访问外部事物中的内容。
这时就将这个事物通过内部类来描述。
为什么内部类就能直接访问外部类中的成员呢?
那是因为内部类其实持有了外部类的引用 外部类.this
对于静态内部类不持有 外部类.this 而是直接使用 外部类名。
【内部类被访问的方式】
情况一:内部类在成员位置上的被访问方式。
成员是可以被指定的修饰符所修饰的。
public:不多见:因为更多的时候,内部类已经被封装到了外部类中,不直接对外提供。
static:
内部类其实也可以定义在外部类的局部位置上。
内部类定义在局部时,只能访问被final修饰的局部变量。
为啥呢?因为编译生产的class中直接操作那个最终数值了。
为什么不能访问非最终的局部变量呢?
内部类的延伸
内部类是可以继承或者实现外部其他的类或者接口的。
好处:通过内部类的方式对类进行继承重写,或者接口进行实现。
通过公共的方式对其内部类对象进行访问。因为通常内部类很有可能被外部类封装其中。
我们就可以通过父类或者接口的方式访问到内部类对象。
匿名内部类
其实就是一个带有内容的子类对象。
格式:new 父类or接口(){子类的内容}
匿名内部类就是内部类的简化形式。
别忘了:匿名内部类有前提,内部类必须要继承父类或者实现接口
————————————————————————————————————————————————----—
小结:本版内容主要是讲了java中的三大思想:封装、继承、多态;个人理解,学习语言,思想最重要,这个要深入理解,重点掌握
- Java基础—面向对象(二)
- JAVA基础六—面向对象二
- java基础——面向对象(二)
- 黑马程序员——Java基础---面向对象(二)
- java基础——面向对象(二)
- 黑马程序员——Java基础-------面向对象(二)
- 黑马程序员——Java基础---面向对象(二)
- Java基础 (二)(面向对象)
- java面向对象基础小结(二)
- Java基础之面向对象(二)
- Java基础<六>----面向对象(二)
- JAVA基础(二)面向对象思想
- java基础之面向对象(二)
- java基础(二):面向对象
- 黑马程序员——java基础---面向对象(二)
- 黑马程序员——Java基础---面向对象<二>
- 黑马程序员——java基础-面向对象(二)
- Java面向对象基础二
- 九章算法面试题9 前k大的和
- ImageLoaderConfiguration详解
- MYsql常用命令
- 开始刷leetcode day10:Maximum Subarray
- asp.net(vs2010)中遇到警告不允许使用“targetFramework”特性。【已解决】
- java基础——面向对象(二)
- Android---37---SQLiteDatabase
- 【Troubleshooting】用户组/权限_导致grid日志不轮循清理_Bug 9595783
- 黑马程序员------------高新面试题之银行调度系统
- CCSpriteFrameCache精灵帧缓存分析(1)
- 3. opencv进行SIFT特征提取
- 省赛总结
- java学习之对象的初始化过程
- 九章算法面试题10 赛马问题