java抽象和多态.docx
- 文档编号:25960870
- 上传时间:2023-06-16
- 格式:DOCX
- 页数:12
- 大小:27.66KB
java抽象和多态.docx
《java抽象和多态.docx》由会员分享,可在线阅读,更多相关《java抽象和多态.docx(12页珍藏版)》请在冰豆网上搜索。
java抽象和多态
1java抽象类
在继承中,抽象是一个非常重要的概念。
类可以是抽象的,方法也可以是抽象的。
建议:
从继承开始,一直使用一个例子不断扩展。
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
如形状类是抽象的类,圆、三角形等是具体类。
用abstract修饰的类就是抽象类。
如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。
但是抽象类中不一定有抽象方法。
在面向对象的概念中,知道所有的对象都是通过类来描绘的,但是反过来却不是这样。
并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
比如:
如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。
使用关键字abstract定义抽象类,一般语法:
[访问权限]abstractclass类名{
成员列表
}
publicabstractclassShapes{
publicabstractvoiddraw();
}
publicabstractclassShapes{
publicvoiddraw(){
//具体代码
}
}
要强调,只要一个类不应该有具体对象,就应该是抽象类,不一定是有抽象方法的。
抽象类的相关概念
用abstract修饰的类就是抽象类。
如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。
抽象类可以有成员属性和非抽象的成员方法。
抽象类不能被实例化,但可以有构造函数。
抽象类只能用作基类,表示的是一种继承关系。
继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。
否则,该类也必须声明为抽象类。
抽象类可以有构造方法,但不能直接实例化,只能用来继承;
抽象类的派生子类应该提供对其所有抽象方法的具体实现;如果抽象类的派生子类没有实现其中的所有抽象方法,那么该派生子类仍然是抽象类,只能用于继承,而不能实例化;
抽象类中也可以包含有非抽象的方法,子类中重写非抽象方法时返回值和参数必须与父类一致;
构造方法和静态方法不可以修饰为abstract。
2java抽象方法
有时候,父类中的某一个方法,每一个子类都要去重写。
这种情况下,父类中的这个方法,就没有必要有方法体,因为子类都不会直接使用,都要重写。
很多学员会觉得既然这样,那么父类中就不应该声明这个方法。
要强调,软件工程中,往往是要有需求分析,设计,再到编码。
在设计阶段,设计人员要想办法让程序员知道某些类中应该实现哪些功能的,也就是whattodo。
父类往往都是设计人员设计的。
因此不能把这样的方法删除掉,如果删除,就没有办法约束子类必须实现这些方法。
这种时候,就把父类中的这样的方法的方法体去掉,就成为抽象方法。
抽象方法定义了whattodo,而howtodo在子类中实现。
在某些情况下,类无法(或者没有必要)提供方法的具体实现,可以将此方法声明成抽象方法;
在类中没有方法体的方法,就是抽象方法;
含有抽象方法的类,一定是抽象类。
抽象方法只需声明,而不需实现某些功能
使用关键字abstract声明抽象方法,一般语法:
[访问权限]abstract返回值类型方法名称(参数列表);
publicabstractvoiddraw();
抽象方法的作用就是定义Howtodo,而whattodo留到子类去实现
在面向对象编程中,抽象是一个非常重要的概念。
作为初学者,首先就是要理解抽象类,抽象方法的使用和作用。
抽象最核心的作用是用来实现应用的可扩展性。
抽象的作用
在面向对象领域,抽象类主要用来进行类型隐藏;也就是使用抽象的类型来编程,但是具体运行时就可以使用具体类型。
利用抽象的概念,能够在开发项目中创建扩展性很好的架构,优化程序。
抽象类,抽象方法,在软件开发过程中都是设计层面的概念。
也就是说,设计人员会设计出抽象类,抽象方法,程序员都是来继承这些抽象类并覆盖抽象方法,实现具体功能。
创建抽象类银行账户,定义抽象方法存款、取款,创建两个子类现金账户类、信用卡账户类,实现抽象方法,定义不同的逻辑。
写测试类测试相关方法。
packagecom.chinasofti.inherit.bak.account;
publicabstractclassAccount{
privateStringid;
privatedoublebalance;
publicAccount(){
System.out.println("Account()");
}
publicAccount(Stringid,doublebalance){
this.id=id;
this.balance=balance;
System.out.println("Account(Stringid,doublebalance)");
}
publicStringgetId(){
returnid;
}
publicvoidsetId(Stringid){
this.id=id;
}
publicdoublegetBalance(){
returnbalance;
}
publicvoidsetBalance(doublebalance){
this.balance=balance;
}
publicvoiddeposit(doubleamount){
balance+=amount;
inform("存款"+amount);
}
publicabstractvoidwithdraw(doubleamount);
publicvoidinform(Stringmsg){
System.out.println("卡号是"+id+"的客户请注意:
"+msg);
}
}
3多态性
要理解多态性,首先要明白运行期类型和编译期类型。
运行期类型与编译期类型
第一种情况:
编译期类型和运行期类型相同
Aa=newA();
a.show();
声明A的时候,使用到的类型A表示对象的类型,被称为编译期类型,在编译期,虚拟机认为a的类型是A,对于a所使用的属性和方法的有效性将到类A中去验证。
构造方法A()中的A是运行期类型,在运行期,将执行运行期类型中的方法
第二种情况:
当有继承关系时,可能发生编译期类型和运行期类型不同的情况,即编译期类型是父类类型,运行期类型是子类类型。
//A类是B类的父类
Aab=newB();
ab.show();
对象ab的编译期类型为父类A类,运行期类型为子类B类。
如果一个引用的编译期类型和运行期类型不同,那么一定是编译期类型与运行期类型有父类子类关系。
ab对象使用的方法,在编译期到类A中去校验,而运行则执行B类的方法
如果一个对象的编译期类型是父类,运行期类型是子类,可以对该对象进行强制类型转换,将其编译器类型转换为与运行期类型相同的类型,即:
Bb=(B)ab;
当编译期类型是父类,运行期类型是子类时,成为这个对象叫父类引用指向子类对象。
父类引用指向子类对象
当编译器类型是父类,运行期类型是子类时,被称为父类引用指向子类对象
classAnimal{
……
}
classCatextendsAnimal{
……
}
classDogextendsAnimal{
……
}
Catm=newCat()
Animalx=newCat()//Animal的引用指向Cat的对象
对象m可以调用猫类中的所有方法,x只能调用动物类中定义的方法,
猫类扩展的新方法不能调用。
多态环境下对属性和方法的调用
当一个对象的编译期类型是父类,运行期类型是子类时,它对属性和方法的调用有一些规则。
尤其对静态方法和属性的调用,与实例方法调用,有所不同,需要格外注意。
多态环境下对成员方法的调用
classAnimal{
voidshow(){
System.out.println(“Anmial");
}
}
classCatextendsAnimal{
voidshow(){
System.out.println(“cat");
}
}
…….
Animalx=newCat()
x.show()//调用的是子类中的方法
简单的说:
编译看左边,运行看右边
多态环境下对静态成员方法的调用
classAnimal{
staticvoidshow(){
System.out.println(“Animal");
}
}
classCatextendsAnimal{
staticvoidshow(){
System.out.println(“Cat");
}
}
…….
Animalx=newCat()
x.show()//调用的是动物类中的静态成员方法。
简单的说:
编译和运行都看左边。
多态环境下对成员变量的调用
classAnimal{
intnum=3;
}
classCatextendsAnimal{
intnum=4;
}
…….
Animalx=newCat()
x.num;//调用的是动物类中的成员变量
简单的说:
编译和运行都看等号左边。
注意:
变量不存在被子类覆写这一说法,只有方法存在覆写。
5多态参数
前面我们反复学习的就是父类引用指向子类对象,实际编程过程中,我们往往是在参数中使用这种特性。
方法参数具有多态性
方法参数多态性的好处:
提高代码的扩展性
6多态环境下对象造型
当存在多态环境时,有时候需要类型转换。
这里将涉及到一个概念叫强制类型转换,但是记住,强制是有前提的,只能强制转换成这个对象的运行期类型
例如
Animalanimal=newCat();
Catcat=(Cat)animal;
因为animal的运行期类型确实是Cat,所以才可以强制转换成Cat
如果Dogdog=(Dog)animal;
将发生ClassCastException
向上造型–又称自动类型提升
classAnimal{
abstractvoideat();
}
classCatextendsAnimal{
voidlook(){
System.out.println("看家");
}
}
………
Animalx=newCat()//向上造型,Cat对象提升到Animal对象
x.eat()//只能使用父类中的方法
x.look()//报错!
不能使用子类中的方法
向上造型的作用是:
提高程序的扩展性。
向下造型–又称向下转型
classAnimal{
abstractvoideat();
}
classCatextendsAnimal{
voidlook(){
System.out.println("看家");
}
}
………
Animalx=newCat()
Catm=(Cat)x;//向下转型
m.eat();//子类可以调用父类的方法
m.look();//子父类中的方法都可以使用
向下造型的作用是:
为了使用子类中的特有方法。
8instanceof操作符
多态环境下的对象有两种类型,其中运行期类型往往在运行时才能确定。
有时候需要根据运行期类型的不同,进行不同处理,这时候就需要使用instanceof操作符来判断一个对象的运行期类型。
instanceof用法
result=对象名称instanceof类型
参数:
result:
布尔类型。
对象名称:
必选项,任意对象表达式。
类型:
必选项,任意已定义的类,可以是API中的类,可以是自定义的类。
说明:
如果对象是这个类型的一个实例,则instanceof运算符返回true。
如果对象不是指定类的一个实例,或者对象是null,则返回false
instanceof运算符是用来在运行时指出对象是否是特定类的一个实例
abstractclassAnimal{
abstractvoideat();
}
classDogextendsAnimal{
voidlook()…...
}
classCatextendsAnimal{
voidcatch()……
}
classInstanceofDemo{
publicstaticvoidmain(String[]args){
method(newDog());
}
}
publicstaticvoidmethod(Animala){
//instanceof:
用于判断对象的具体类型。
if(ainstanceofCat){
Catc=(Cat)a;
c.catch();
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java 抽象