面向对象(继承、final关键字、抽象类、接口)

继承(extends)
如果父类中有的功能不应该是子类所具备的,那就不要继承
 
 
---------------------------------------------------------------------------------
java只支持单继承,不支持多继承,但支持多层继承(a-->b-->c)
为什么?
如图,c继承a,b,调用show方法,因为a,b都有show方法,那不知道该调用谁啊
 
--------------------------------------------------------------------------
如果子类含有父类名称相同的变量,则会打印子类的,其实是省略了关键字this
如果想打印父类的那个变量,则用关键字super修饰
 
 
如图,子类中的num已经注释了,此时在打印num,则将打印父类的num,
num即 super.num
--------------------------------------------------------------------------
重写(覆盖)
如果子父类中有相同的方法,子类new一个对象调用该方法时,会运行子类的方法
父类的方法其实也还在,只是没有运行
 
通过super继承父类的内容,并拓展子类的功能
如,子类不必在写number,而是继承父类的
super.show();
----------------------------------------------------------------------------
权限:private、  默认权限(什么也不写)、public
注意:子类覆盖父类,必须保证子类权限大于父类权限
如图,子父类的speak方法不能成为覆盖
为什么呢,因为父类的speak方法为private,父类之外是看不见这个方法的,
所以子类不知道父类有一个speak方法,所以怎么去覆盖啊

重写和重载
重载,同一个类,参数类型或者个数不同
重写,不同类中,函数名,参数。。都相同,里面的内容不同
 
注:覆盖必须和子类函数名等一模一样,只是内容不同(也可相同,但没意义啊)
如 父类 int show()
子类 void show()
会报错,为什么,首先,show方法在子类中没有实现重写,因为返回值类型不同
然后,子类中就会存在两个返回值类型不同的show方法,当调用。show时,
系统不知道要调用哪个show方法
-----------------------------------------------------------------------------
上面这段代码输出的是:
fu run;
zi run;
---------------------------
知道了子类构造函数里面都有一个隐式得得super();
会调用父类的无参构造函数,那么,如果想调用父类的有参构造函数呢
就用super(参数);
 
看下面这个例子
有参数的构造函数,一面已经有了this,就不能有super了
其实this是调用的无参构造函数zi();
而zi()里面的第一行默认是super,即调用父类的无参构造。。
即,子类中至少会有一个构造函数去访问父类的构造函数
 

为什么this(),super()不能同时在构造函数中,因为他们都在第一行
为什么都在第一行,因为初始化动作要先做。。
-----------------------------------------------------------------
final
目的是什么:为了保证有些东西不能被继承,就用final修饰

如下面这个类,为最终类,就不能被继承
--------------------------------
3.被final修饰的方法不可以被复写
上面整个类都不能被复写,但是如果我想让类中一部分方法可以被复写,
另一部分可以被复写,那就用final修饰类中的方法
如图,show2()可以被复写,show1()不能被复写
------------------------------------
4.被final修饰的变量是一个常量,只能赋值一次,既可以修饰成员变量,也可修饰局部变量
成员变量:
final int x= 3;
局部变量:
void show(){
final int num = 5;
}
那么,final用在什么地方呢,举个栗子
 final double PI = 3.14;
常量的定义:所有字母大写,多个单词的话,单词之间下划线连接
---------------------------
而final修饰的变量,前面通常会加一个修饰符static静态,因为静态的内容会被方法区中共享
所以就是这种形式:public static final double PI = 3.14;
------------------------------
目前学到的可以修饰类的修饰符有:
public / final / 默认修饰符(什么都不加)
----------------------------------------------------------------------------------------
抽象类
抽象类大体上是用来继承的 -_-
多个类中出现相同的功能,但是功能主体不同,这时可以上向抽取。
这时,只抽取功能定义,而不抽取功能主体
抽象类是怎么来的,举个栗子
Person{
            void study(){
                Syso("study");
    }
}
 
Student extends Person{
            void study(){
                Syso("study");
    }
}
Worker extends Person{
            void study(){
                Syso("worker");
    }
}
看上面三个类,学生,工人都继承人,都有study方法,但都不一样,
所以,此时人类里定义的学习的方法体就没有任何意义了(因为一直被复写)
所以,人类里的syudy方法就可以演变成:
-->study(){}-->study();
但是,成为这样子后,你看到这个方法,不知道具体是干嘛的(因为没有方法体)
所以,可以定义为抽象
abstract void study();
抽象方法必须放在抽象类中
abstract class Student{
    abstract void study();
}
-------------------------------------------------------
抽象类特点:
1.抽象方法一定在抽象类中
2.抽象方法和抽象类都必须被abstract修饰
3.抽象类不可以用new创建对象,即抽象类不可以实例化,因为调用抽象方法没有意义
因为抽象方法两个方法体都没有,你调用它干啥
4.抽象类中的抽象方法要被使用,子类必须复写抽象类中所有的抽象方法
----------------------------------------------------------------------
那抽象类有什么用呢:
抽象类就是定义一个框架,举个栗子
老板说要开发一款手机,要有屏幕,有按键。。。
但具体怎么做,老板不管
abstract class 手机{
    abstract void 屏幕();
    abstract void 按键();
}
--------------------------
抽象类可以强制子类去做些事情
上面的例子,我如果在老板的公司做手机,我就必须弄个屏幕,弄个按键
注:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象(java类库中有这样的例子)
抽象类中可没有抽象变量
抽象类和普通类的区别就是:
抽象类比一般类多了抽象函数;
抽象类不可以被实例化
------------------------------------------------
上面总结了没有抽象变量,但并不代表没有普通变量
如图,抽象类中是可以有普通方法和变量的
子类继承了抽象类之后,必须要重写抽象类的抽象方法sleep()
--------------------------------------------------------------
设计模式:
模板方法设计模式
什么是模版方法呢?
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,
那么这时就将不确定的部分暴露出去。由该类的子类去完成。
比如这个类,获取运行一段代码的时间
中间的runcode方法是变化的内容,那么,就把runcode暴露出去,让别人根据需要复写
SubTime这个类继承GetTime类,并实现抽象方法runcode()
在main函数中,实例化SunTime类,调用父类的getTime方法
 
--------------------------------------------------------------
接口
当抽象类中的方法都是抽象的,那么该类可以通过接口来表示
class 用于定义类;
interface用于定义接口
注:接口中定义的是常量,
所以要大写 public static final double PI = 3.14;
---------------------------------------------------
接口的示例
interface Inter
{
    public static final int NUM = 3;
    public abstract void show();
}
看,我把接口中的成员定义成这个样子行不行啊
答案是可以的,接口中的成员都有固定的修饰符,如果你没有加的话,
系统也会自动给你加上,但是这样写不规范
---------------------------------------------------------
接口也不能创建对象(因为有抽象方法),只能实现接口implements
子类必须重写接口中的所有抽象方法才能实例化,否则,子类是一个抽象类
------------------------------------------------
接口可以被类多实现-->即,一个类可以实现多个接口,即:多实现
首先,java是不支持多继承的(一个类同时继承多个类),
但是不支持的话有弊端,怎么弥补呢,就用接口的多实现弥补
为什么多继承不能行,多实现就可以呢,因为
多继承,可能会出现相同的方法名,但是,方法体不一样,不知道调用哪个;
但是,多实现里面都是抽象方法,不会出现这种情况
interface A
{ void methodA();
}
interface B 
{ void methodB();
}
 
class C implements A,B
public void methodA(){}
public void methodB(){}
}
----------------------------------------
一个类在继承另一个类(单继承)的同时,还能实现多个接口
------------------------------------------
接口与接口之间也可以继承,可以实现多继承
原理很简单,接口多继承不会出现类多继承那种同名函数,不同方法体不知调用谁的问题
因为都是抽象方法。。。
-----------------------------------
如下图,接口C继承了接口 A,B
类D实现了接口C
那么,在类中,就要把A,B,C接口中的抽象方法都复写
---------------------------------
下面这种情况是不允许出现的,
接口A,B分别定义了返回值类型不同的show()方法,
类D实现了A,B,那么,D就要分别重写两个返回值不同的show方法
如果这样的话,那就遇到问题:当创建D的实例对象的时候,调用D的show方法,不知道该调用哪个
所以,如果出现这样的定义,java会报错
 
 
看到上面那个图片,别人问你的 java支持多继承吗
你就可以机智的回答:java支持多继承,但是,仅限于接口与接口之间 呵呵~
-----------------------------------------------------------
接口和继承
看代码,张三是学生,所以,它具备学生的共性;
但是,至于抽烟这个接口,并不是所有学生都抽烟,
所以,谁抽烟谁就实现抽烟接口
即:基本功能定义在父类中,拓展功能定义在接口中
abstract class Student
{
    abstract void study();
    void sleep()
    {
        System.out.println("sleep");
    }
 
}
 
interface Smoking
{
    void smoke();
}
 
class ZhangSan extends Student implements Smoking
{
    void study(){}
    public void smoke(){}
}
 
 
 
原文地址:https://www.cnblogs.com/aisi-liu/p/4164385.html