大家好,我是KookNut39也是Tommy,在CSDN写文,写Java时候我是Tommy,分享一些自己认为在学习过程中比较重要的东西,致力于帮助初学者入门,希望可以帮助你进步。感兴趣的欢迎关注博主,和博主一起学习Java知识。大家还可以去专栏查看之前的文章,希望未来能和大家共同探讨技术。
面向对象特征——多态
学习多态之前我们应该先学习抽象类和接口,因为抽象类和接口是实现多态的前提。
1.抽象类
如果自上而下在类的继承层次结构中上移,位于上层的类更具有一般性,可能更加抽象。从某种角度看祖先类更具有一般性,人们只将它作为派生其他类的基类,而不是构造你想要的特定的实例。 ——Java核心技术 (卷一)
上面这段话讲明了抽象类是怎么来的,和抽象类的用途。那么什么是抽象类呢?如果一个类中没有包含足够的信息 来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在 ,成员变量、成员方法和构造方法。
用abstract 修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须 定义成抽象类。
特点 :
抽象类不能被实例化,但可以有构造函数,因为抽象类中含有无具体实现 的方法,所以不能用抽象类创建对象。
抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实现其中的所有 抽象方法,而已实现方法的参数、返回值 要和抽象类中的方法一样 。否则,该类也必须声明为抽象类。
抽象方法 抽象方法充当着占位方法的角色,它们在子类中具体实现。
抽象方法是一种特殊的方法:它只有声明,而没有具体的实现
抽象方法必须 用abstract关键字进行修饰
[ 访问权限] abstract class 类名 {
//成员列表
}
注意 :
抽象类,抽象方法,在软件开发过程中都是设计层面 的概念。也就是说,设计人员会设计出抽象类,抽象方法,程序员都是来继承 这些抽象类并覆盖抽象方法,实现具体功能。 有些程序员认为,在抽象类中不能包含具体方法。建议尽量将通用的属性和方法(不管是不是抽象的)放在基类中(不管是不是抽象类)。 即使不含抽象方法也可以将类声明为抽象类。 抽象类不能实例化。
2.接口
在生活中我们见的最多的就是USB接口,电脑上的接口,鼠标接口,U盘接口。那么这些接口是如何工作的呢?
电脑上的USB接口本身没有实现任何功能,意思就是,当我们什么都不给它插入时,它没有什么用,有没有它都不会对电脑造成什么影响,但是它规定了数据传输要求,可以被许多的设备实现,当接入鼠标时就把鼠标和电脑连接起来,它不会把鼠标当作U盘来用,原因就在于,实现什么功能不是靠接口来决定,是看谁实现了它。
接口用来描述类应该做什么,而不指定它具体怎么做。一个类可以实现一个或多个接口。 注意 :接口不是类,而是对希望符合这个接口的类的一组需求。
接口的定义 :
//中括号中的内容表示可以有可以没有
[ 访问修饰符] interface 接口名称 [ extends 其他的接口名1 , …. 其他的接口名n] {
//接口类必须用interface关键词修饰
//接口中的属性默认都是public static final修饰
int num = 10 ;
//所有方法默认都是public abstract修饰
void method ( ) ;
}
接口的特性 :
接口中的变量都是静态常量 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。 接口中每一个方法也是隐式抽象的,默认为public abstract 。 接口中声明的属性默认为 public static final 的; 接口不是被类继承了,而是要被类实现 。 接口不能实例化对象(无构造方法),但可以声明对象的引用。(多态性) 多个类可以实现同一个接口。 一个类可以实现多个接口,但只能继承一个类。 与继承关系类似,接口与实现类之间存在多态性。 一个接口能继承其它多个接口。 当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
面向接口编程时:
关心实现类有何能力,而不关心实现细节
面向接口的约定而不考虑接口的具体实现
接口存在的意义:Java中一个类只能有一个父类,所以用接口可以实现多继承的逻辑 。
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量 和方法的定义 ,而没有变量 和方法的实现 。
接口的使用 :
接口的使用:类使用implements 关键字实现接口。在类声明中,Implements关键字放在class声明后面。
[ 访问修饰符] class 类名 implements 接口名1 ,接口名2 ……{
}
结合继承:
[ 访问修饰符] class 类名 extends 父类名 implements 接口名1 ,接口名2 ……{
}
多态
上一篇博客提到多态就是同一种事物,在不同时刻表现不同的状态
多态存在的三个必要条件:
要有继承(或者接口的实现)(前提条件)
要有重写(前提条件)
父类引用指向子类对象
多态环境下对成员方法的调用
class Animal {
void show ( ) {
System . out. println ( "Anmial" ) ;
}
}
class Cat extends Animal {
void show ( ) {
System . out. println ( "cat" ) ;
}
}
Animal x = new Cat ( ) ;
x. show ( ) ; //调用的是子类中的方法
有图有真相:
就是编译看左边,运行看右边 。
多态环境下对静态成员方法的调用
class Animal {
static void show ( ) {
System . out. println ( "Animal" ) ;
}
}
class Cat extends Animal {
static void show ( ) {
System . out. println ( "Cat" ) ;
}
}
Animal x = new Cat ( ) ;
x. show ( ) ; //调用的是动物类中的静态成员方法。
就是说:编译和运行都看左边
多态环境下对成员变量的调用
class Animal {
int num = 3 ;
}
class Cat extends Animal {
int num = 4 ;
}
Animal x = new Cat ( ) ;
System . out. println ( x. num) ; //调用的是动物类中的成员变量。
就是说:编译和运行都看左边 。
注意 :变量不存在被子类覆写这一说法,只有方法存在覆写。
方法参数具有多态性
class Animal {
void eat ( ) { }
}
class Cat extends Animal {
void eat ( ) { }
}
class Dog extends Animal {
void eat ( ) { }
}
//方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象
void method ( Animal animal) {
animal . eat ( ) ;
}
方法参数多态性的好处:提高代码的扩展性
向上转型
class Animal {
void eat ( ) {
System . out. println ( "吃" ) ;
}
}
class Cat extends Animal {
void look ( ) {
System . out. println ( "看老鼠" ) ;
}
}
Animal x= new Cat ( ) ; //向上造型,Cat对象提升到Animal对象
x. eat ( ) ; //只能使用父类中的方法
x. look ( ) ; //报错!不能使用子类中的方法
向下转型
class Animal {
void eat ( ) {
System . out. println ( "吃" ) ;
}
}
class Cat extendsAnimal{
void look ( ) {
System . out. println ( "看老鼠" ) ;
}
}
Animal x= new Cat ( ) ;
Cat m= ( Cat ) x; //向下转型
m. eat ( ) ;
m. look ( ) ; //子父类中的方法都可以使用
final关键字
final 用于声明属性,方法和类
属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期都不能修改。
方法:子类里不可被覆盖。(不能被重写)
方法参数:对参数做final修饰,在方法参数前面加final关键字,为了防止数据在方法体中被修改。
类:不能被定义为抽象类或是接口,不可被继承。(不能当父类)
final属性赋值
在声明时同时赋值,往往与static一起使用
声明时不赋值时,必须在构造方法中逐一赋值
总的原则:保证创建每一个对象的时候,final属性的值是确定的
本次的分享到这里就结束了,码字不易,如果喜欢,赏个点赞+评论+收藏🤞🤞🤞,感谢您的支持
文中举例,用词等可能有不当的地方,望谅解,欢迎在评论区批评指正! 参考书籍:Java核心技术 卷1(11版)