文章目录
多态的概念
多态是指在动态绑定的前提下,利用父类引用实例化子类对象来调用重写,实现不同对象(或者方法)表现出不同的状态的一种面向对象的特性
例如 打印机
都是一张白纸去打印,但是却能打印出不同的画面
多态出现的前提 – 动态绑定
动态绑定要满足向上转型,重写和通过父类引用调用父类和子类重写的方法
重写
概念:指的是子类对父类能够访问的方法进行重新编写,即返回类型,方法名,形参都不发生改变
以打印图像为例 看代码
class Print{
public void printShape(){
System.out.println("打印图形");
}
}
class Circle extends Print{
public void printShape(){
System.out.println("打印圆圈");
}
}
其中,printShape方法就发生了重写
并且子类会优先调用子类的重写方法
注意事项
1.要被重写的方法不能被final, private, static修饰
若是被final修饰就代表着该方法被封装了,不能修改
若是被private修饰表示该方法只能在父类中使用
若是被static修饰代表着该方法只与类有关和对象无关
2.子类的访问修饰限定权限要大于等于父类
3.不要在构造方法中调用重写
扩展:重写和重载的区别
- 重写必须方法名,参数,返回值都相同
重载则是方法名相同,参数,返回值都有不同 - 重写在编译时,不能确定调用哪个方法,只有在运行时才确定具体调用哪个方法
重载在编译时就可根据传参的不同确定调用哪个方法
向上转型
向上转型值得是用父类的引用来创建子类的对象
能够使得代码更加简单灵活
使得父类引用能够通过重写调用子类的方法和属性
但是父类的引用只能直接的访问父类的方法和属性
class Print{
public void printShape(){
System.out.println("打印图形");
}
}
class Circle extends Print{
@Override
public void printShape() {
System.out.println("打印圆圈");
}
}
public class Polymorphic {
public static void main(String[] args) {
Print print = new Circle(); //如此就是向上转型
}
}
扩展:向下转型
和向上转型类似,只不过反了一下,用子类的引用构建父类的对象,但是向下转型还需要强转一下父类的对象
class Print{
public void printShape(){
System.out.println("打印图形");
}
}
class Circle extends Print{
@Override
public void printShape() {
System.out.println("打印圆圈");
}
}
public class Polymorphic {
public static void main(String[] args) {
Circle circle = (Circle) new Print();
//此处即是向下转型
}
}
向下转型非常的不安全
那么为什么向上转型为什么不会出现这种现象呢?
其实也很好理解,就比如,圆圈是图形,但是图形不只有圆圈
通过父类引用调用父类和子类重写的方法
如果子类有父类的重写方法,那么即使是用父类的引用,优先执行的还是子类的重写
class Print{
public void printShape(){
System.out.println("打印图形");
}
}
class Circle extends Print{
@Override
public void printShape() {
System.out.println("打印圆圈");
}
}
public class Polymorphic {
public static void main(String[] args) {
Print print = new Circle();
print.printShape(); //父类引用调用重写方法
}
}
//输出
打印圆圈
动态绑定实际上也就是将父类的重写方法和子类的重写方法绑定到了一起
在运行父类引用调用重写方法时,父类重写方法的地址发生改变,改变为子类的重写方法的地址
扩:静态绑定
静态绑定最经典的例子就是,重载
静态绑定和动态绑定的区别就在于
动态绑定的方法,在编译时,不能确定调用哪个方法,只有在运行时才确定具体调用哪个方法
静态绑定的方法,在编译时就可根据传参的不同确定调用哪个方法
多态的运用
多态实际上是一种思维
能够极大的简化代码,实现代码的复用,还能减少if-else 语句
由对象体现多态
abstract class Base{
public abstract void func();
}
class A extends Base{
public void func(){
System.out.println("A");
}
}
class B extends Base{
public void func(){
System.out.println("B");
}
}
public class Abstracte {
public static void main(String[] args) {
Base base = new A();
base.func();
base = new B();
base.func();
//由对象体现多态
}
}
//输出
A
B
如此就是,在动态绑定的前提下,不同的对象A,B输出了不同的字母
由方法体现多态
abstract class Base{
public abstract void func(Base base);
}
class A extends Base{
public void func(Base base){ //此处发生向上转型
func1(base); //通过重写调用子类特有的方法
}
public void func1(Base base){
System.out.println("A");
}
}
class B extends Base{
public void func(Base base){
func1(base); //通过重写调用子类特有的方法
}
public void func1(Base base){
System.out.println("B");
}
}
public class Abstracte {
public static void main(String[] args) {
A a = new A();
a.func(a);
B b = new B();
b.func(b);
//由方法体现多态
}
}
//输出
A
B
由方法和对象一起体现多态
abstract class Base{
public abstract void func(Base base);
}
class A extends Base{
public void func(Base base){
func1(base);
}
public void func1(Base base){
System.out.println("A");
}
}
class B extends Base{
public void func(Base base){
func1(base);
}
public void func1(Base base){
System.out.println("B");
}
}
public class Abstracte {
public static void main(String[] args) {
Base base = new A();
base.func(base);
Base base1 = new B();
base1.func(base1);
}
}
//输出
A
B
当在实现多态过程中的子类过多时,可利用数组来简化代码
abstract class Base{
public abstract void func(Base base);
}
class A extends Base{
public void func(Base base){
func1(base);
}
public void func1(Base base){
System.out.println("A");
}
}
class B extends Base{
public void func(Base base){
func1(base);
}
public void func1(Base base){
System.out.println("B");
}
}
public class Abstracte {
public static void main(String[] args) {
A a = new A();
B b = new B();
Base[] base = {a,b};
for(Base x : base){ //遍历数组
b.func(b);
}
}
}
//输出
A
B
抽象类 – abstract
抽象类就是含有抽象方法的类
抽象方法
特点:定义方法但是不写出具体的方法内容
abstract class Base{ //抽象类Base
public abstract void func(); //抽象方法
}
抽象方法只能出现在抽象类中
但是抽象类中不只有抽象方法,还可以有普通类有的方法
抽象类的运用
抽象类最大的用处就在于继承
抽象类的抽象方法必须在子类中实现
abstract class Base{
public abstract void func();
}
class A extends Base{
public void func(){
System.out.println("A"); //重写抽象方法
}
}
public class Abstracte {
public static void main(String[] args) {
Base base = new A();
base.func();
}
}
抽象类的注意事项
1. 抽象类需要用abstract修饰
例如抽象类Base
abstract class Base{ //抽象类Base
public abstract void func();
}
2.抽象类不能被实例化
因此,抽象类存在的最大的意义就是继承和动态绑定
虽然抽象类不能实例化,但是抽象类的引用可以实例化子类的对象
public static void main(String[] args) {
Base base = new A(); //抽象类Base实例化子类A对象
base.func();
}
3.抽象类中可以有抽象方法,也可以有非抽象类方法
但是抽象方法只能在抽象类中定义
abstract class Base{
public abstract void func(); //抽象方法
public void func1(){ //非抽象方法
System.out.println("basebase");
}
public int B = 1314520; //普通成员变量
}
4.若抽象类中有抽象方法,那么继承它的普通子类就必须重写抽象方法
即使继承的子类依旧是抽象类,那么第二代普通子类也依旧要重写抽象方法
abstract class Base{
public abstract void func();
public void func1(){
System.out.println("basebase");
}
public int B = 1314520;
}
abstract class A extends Base{ //套娃:继承类A继承继承类Base
//不用重写抽象方法
}
class B extends A{ //普通类B继承抽象类A
public void func(){ //还是要重写
System.out.println("B");
}
}
抽象方法逃不过重写
5.抽象方法必须满足重写的规则
重写的方法不能被final,static,private修饰
结语
以上就是我脑子中的Java多态和抽象类的基础知识啦!!
若是文章有什么错误的地方,希望家人们能多和我交流,感谢!!