-----------android培訓、java培訓、java學習型技術博客、期待與您交流!------------
一、繼承
繼承是面向對象的一個重要特徵。當多個類中存在相同屬性和行爲時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行爲,只要繼那個類即可。多個類中存在相同屬性和行爲時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行爲,只要繼承那個類即可。
通過extends關鍵字可以實現類與類的繼承
class 子類名 extends 父類名 {}
單獨的這個類稱爲父類,基類或者超類;這多個類可以稱爲子類或者派生類。
有了繼承以後,我們定義一個類的時候,可以在一個已經存在的類的基礎上,還可以定義自己的新成員。
繼承的好處:
提高了代碼的複用性
多個類相同的成員可以放到同一個類中
提高了代碼的維護性
如果功能的代碼需要修改,修改一處即可
讓類與類之間產生了關係,是多態的前提
其實這也是繼承的一個弊端:類的耦合性很強
弊端
耦合性增強,違背了我們的開發原則
高內聚,低耦合
高內聚:能自己乾的事兒從來不求別人
低耦合:類與類直接不要產生太多依賴
特點:
Java只支持單繼承,不支持多繼承。
一個類只能有一個父類,不可以有多個父類。
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2...//error
Java支持多層繼承(繼承體系)
class A{}
class B extends A{}
class C extends B{}
注意事項:
父類私有成員,子類不能繼承
子類不能繼承父類構造方法
不要爲了部分功能去繼承
類與類之間存在 is a 關係時使用繼承
演示用例:
class PersonTest{
public static void main(String[] args){
Student s = new Student("闖闖", 18,"czbk001");
System.out.println(s.name +"--" + s.age +"--"+ s.studyNum);
s.study();
s.eat(); // 繼承來的
s.sleep(); //繼承來的
Teacher t = new Teacher("老武", 48 ,"czbk008");
System.out.println(t.name +"--" + t.age +"--"+ t.workNum);
}
}
class Person{
String name ;//姓名
int age; //年齡
int money;
public void eat(){
System.out.println("下雨天 ,吃點熱乎的 ");
}
public void sleep(){
System.out.println("下雨天 ,特別適合補一覺 ");
}
}
class Student extends Person{
String studyNum; //學號
Student(){}
Student(String name , int age, String studyNum){
this.name = name;
this.age = age;
this.studyNum = studyNum;
}
public void study(){
System.out.println("下雨天 , 好好學習");
}
}
class Teacher extends Person{
String workNum; //工號
Teacher(){}
Teacher(String name , int age, String workNum){
this.name = name;
this.age = age;
this.workNum = workNum;
}
public void work(){
System.out.println("下雨天 , 好好講課");
}
}
成員變量的關係:
當父類與子類中變量名字不同時:調用對應的變量即可
當父類與子類中的變量名字相同 :
1.子類使用的子類自己的
2.子類想使用父類的變量,使用super關鍵字
this:前提是創建了當前對象 ,this 是當前對象的引用
super:沒有創建父類對象,super可以理解爲父類的引用,但其真正代表的是,父類存儲空間的標識.
我們只需掌握:通過super關鍵字,子類可以訪問到父類成員
演示用例:
class VarDemo{
public static void main(String[] args){
//創建子類對象
Zi z = new Zi();
z.show2();
System.out.println();
}
}
class Fu{
int num1 =30;
public void show(){
System.out.println(num1);
}
}
class Zi extends Fu{
int num1=20;
public void show2(){
int num1 = 10;
System.out.println(num1); //10
System.out.println(this.num1); //20
System.out.println(super.num1); //30
}
}
成員方法:
當方法名不同時,父類有的子類可以直接用
當方法名相同時,調用子類中的方法(子類和父類出現了一模一樣的方法聲明,包括 方法名,返回值類型,參數列表,這裏,父類的方法會被子類的方法重寫)
演示用例:
class AnimalTest{
public static void main(String[] args){
Animal a = new Animal();
a.eat();
Cat c = new Cat();
c.eat();
c.sleep();
Dog d = new Dog();
d.eat();
}
}
class Animal{
String name;
int leg;
private void sleep(){
System.out.println("號的睡眠是旺盛精力的保障哦!");
}
public void eat(){
System.out.println("吃飽飯纔有力氣戰鬥↖(^ω^)↗");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("小魚兒,我的最愛。");//eat()方法重寫
}
}
class Dog extends Animal{
public void eat(){
System.out.println("我不挑食的!");//eat()方法重寫
}
}
注意事項:
1.父類私有的不能重寫
2.子類重寫的時候,權限不能更低
3.靜態修飾的成員方法,只能用靜態方法來重寫
4.當你重寫方法的時候,聲明保持一致(返回值類型,方法名,參數列表);
Override(重寫)和Overload(重載)的區別?
1.類的範圍不一樣
重寫:子父類
重載:同一類
2.方法聲明:
重寫:返回值類型,方法名,參數列表 一模一樣
重載:方法名一樣,參數列表不同, 返回值類型無關
構造方法:
不能繼承,但是我們可以調用父類的構造方法
子類的構造方法默認調用 父類的無參構造.
因爲構造方法是給類初始化數據的,子類如果想使用父類的成員變量的值,那麼必須用父類的先構造初始化.
注意事項:
1.父類中的成員變量被private修飾了,還得對外提供一個公共的訪問方式.構造方法就是public的,那麼子類想構造,就可以直接調用父類的構造方法了!
2.父類中沒有無參構造
方式一:使用super中的有參構造
方式二:使用this中的有參構造,前提是有參構造也得訪問到父類super有參構造中
3. super和this 必須在第一行,並且只能有一個
演示用例:
class Fu {
static {
System.out.println("靜態代碼塊Fu");
}
{
System.out.println("構造代碼塊Fu");
}
public Fu() {
System.out.println("構造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("靜態代碼塊Zi");
}
{
System.out.println("構造代碼塊Zi");
}
public Zi() {
System.out.println("構造方法Zi");
}
}
class Test1{
public static void main(String[] args){
Zi z = new Zi();
}
}
參考結果:
---------- java ----------
靜態代碼塊Fu
靜態代碼塊Zi
構造代碼塊Fu
構造方法Fu
構造代碼塊Zi
構造方法Zi
輸出完成 (耗時 0 秒) - 正常終止
Final:
Final關鍵字是最終的意思.
可以修飾類,成員變量,成員方法。
修飾類,類不能被繼承,這樣就可以避免被繼承、被子類複寫功能。
修飾變量,變量就變成了常量,只能被賦值一次
修飾方法,方法不能被重寫
當在描述事物時,一些數據的出現值是固定的,那麼這時爲了增強閱讀性,都給這些值起個名字。方便於閱讀。而這個值不需要改變,所以加上final修飾。
作爲常量:常量的書寫規範所有字母都大寫,如果由多個單詞組成,單詞間通過_連接。
內部類定義在類中的局部位置上時,只能訪問該局部被final修飾的局部變量。
抽象類
沒有辦法具體描述的類,比如 動物,水果 ,工具 ,蔬菜 , 情感....
格式:
類: abstract class 類名 { }
方法: public abstract void eat();
注意:抽象方法是沒有方法體
抽象類中可以沒有抽象方法 ,但是如果有抽象方法,那麼此類必然爲抽象類
抽象類的特點
1、抽象類和抽象方法必須用abstract關鍵字來修飾。
2、抽象類不一定有抽象方法,有抽象方法的類一定是抽象類
3、抽象類不能實例化,也就是不可以用new創建對象。
抽象類是具體事物抽取出來的,本身是不具體的,沒有對應的實例。
那麼,抽象類如何實例化呢?
按照多態的方式,由具體的子類實例化。其實這也是多態的一種,抽象類多態。
4、抽象類的子類
要麼是抽象類
要麼重寫抽象類中的所有抽象方法
格式:修飾符abstract返回值類型 函數名(參數列表);
注:抽象類中可以有非抽象的方法。
下面通過一個實例,來說明抽象類的使用:
演示用例:
具體事物:基礎班老師,就業班老師
共性:姓名,年齡,講課。
class AbstractTeacher{
public static void main(String[] args){
Teacher tr = new Basic_Teacher("XX",28);
tr.teach();
Teacher tr1 = new Obtain_Employment_Teacher("ZZ",33);
tr1.teach();
}
}
abstract class Teacher{//定義抽象類,類名爲Teacher
private String name;//變量私有化
private int age;
Teacher(){}
Teacher(String name,int age){//有參構造
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public int getName(){
return age;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public abstract void teach();//抽象方法teach
}
class Basic_Teacher extends Teacher{//基礎班老師類繼承Teacher
Basic_Teacher(){}
Basic_Teacher(String name,int age){
super(name,age);
}
public void teach(){
System.out.println("講基礎知識");//重寫teach
}
}
class Obtain_Employment_Teacher extends Teacher{//定義就業班教師類,繼承Teacher
Obtain_Employment_Teacher(){}
Obtain_Employment_Teacher(String name,int age){
super(name,age);
}
public void teach(){
System.out.println("講解WEB知識");//重寫teach方法
}
}
abstract 不能和哪些關鍵字共存?
private 衝突 -- 對子類隱藏,無法被複寫,而 abstract 必須讓子類重寫
final 衝突 -- 不能被重寫,矛盾
static 無意義-- 類名調用,沒有方法體,無意義
抽象類的成員特點
成員變量
可以是變量
也可以是常量
構造方法
有構造方法,但是不能實例化
那麼,構造方法的作用是什麼呢?
用於子類訪問父類數據的初始化
成員方法
可以有抽象方法 限定子類必須完成某些動作
也可以有非抽象方法 提高代碼服用性
接口
接口,本質就是一種規則。作用就是擴展類的功能。
格式爲:
interface 接口名{}
相當於定義了規則
接口中可以寫方法,但是必須是抽象的.
Class 子類名 implements接口名{}
相當於給類擴展了接口的功能,需要重寫接口的所有抽象方法
接口特點
接口用關鍵字interface表示
格式:interface 接口名 {}
類實現接口用implements表示
格式:class 類名 implements 接口名 { }
接口不能實例化
那麼,接口如何實例化呢?
按照多態的方式,由具體的子類實例化。其實這也是多態的一種,接口多態。
接口的子類
要麼是抽象類
要麼重寫接口中的所有抽象方法
接口成員特點:
成員變量
只能是常量
默認修飾符 public static final
構造方法
沒有,因爲接口主要是擴展功能的,而沒有具體存在
成員方法
只能是抽象方法
默認修飾符 public abstract
類與類,類與接口以及接口與接口的關係:
類與類
繼承關係,只能單繼承,但是可以多層繼承
類與接口
實現關係,可以單實現,也可以多實現。還可以在繼承一個類的同時實現多個接口。因爲接口中的方法都是抽象的,都需要子類重寫,所以可以多繼承。
接口與接口
繼承關係,可以單繼承,也可以多繼承。原因同上,都是因爲接口中的類都是抽象的,需要被子類重寫。
接口與抽象類的區別
成員區別
抽象類 變量,常量;有抽象方法;抽象方法,非抽象方法
接口 常量;抽象方法
關係區別
類與類 繼承,單繼承
類與接口 實現,單實現,多實現
接口與接口 繼承,單繼承,多繼承
設計理念區別
抽象類 被繼承體現的是:”is a”的關係。共性功能
接口 被實現體現的是:”like a”的關係。擴展功能
演示用例:
/*
動物類:姓名,年齡,吃飯,睡覺。(抽象)
動物培訓接口:數數 (接口)
貓繼承動物類
部分貓繼承貓類並實現跳高接口
通過抽象類測試基本功能。
通過接口測試擴展功能。
*/
class CircusCatDemo{
public static void main(String[] args){
CircusCat cc = new CircusCat("加菲",4);
cc.fight();
cc.count();
cc.sleep();
cc.eat();
}
}
abstract class Animal{//定義抽象類,類名爲Animal
private String name;
private int age;
Animal(String name,int age){
this.name = name;
this.age = age;
}
public void sleep(){
System.out.println("白天睡覺覺,晚上纔是我的天下的說,喵~~~~");
}
public abstract void eat();//抽象方法 eat()
}
class Cat extends Animal{//定義貓類繼承抽象類Animal
Cat(String name,int age){
super(name,age);
}
public void eat(){
System.out.println("還是魚好吃啊");
}//重寫抽象方法
}
interface Train{//定義訓練接口
public abstract void count();//數數方法
}
interface Nature{//定義Nature接口
public abstract void fight();
public abstract void jump();
}
class CircusCat extends Cat implements Train,Nature{//定義馬戲貓類繼承貓類並實現Train和Nature接口
CircusCat(String name,int age){
super(name,age);
}
public void count(){
System.out.println("1,2,3,4,5,6真當我是白癡的嗎,喵?");
}//重寫接口方法
public void fight(){
System.out.println("我討厭狗,貓的天敵不只是老鼠的說,喵~~~");
}
public abstract void jump(){
System.out.println("我跳的很高的,喵");
}
}
抽象類作爲形式參數,要的是抽象類的子類對象
牌有很多種-- 麻將,三國殺,多米諾骨牌
所有我們牌定義爲抽象類
接口作爲形式參數,要的是實現了接口的子類對象
牌還有擴展功能 -- 變魔術
class PersonTest{
public static void main(String[] args){
//創建人的對象
Person p = new Person();
//創建紙牌的對象
Card c = new Card();
//p.play(c);
//創建牌的對象
//Pai pai = new Card();
Pai pai = new MaJiang();
p.play2(pai);
//變魔術
Magic m = new Card();
p.play3(m);
}
}
class Person{
//人打紙牌的方法
public void play(Card c){
c. bang();
c.shunzi();
}
//人玩牌
public void play2(Pai p){
p.fun();
}
//人用紙牌變魔術
public void play3(Magic m){
m.moShu();
}
}
//定義接口
interface Magic{
public abstract void moShu();
}
//抽象的牌類
abstract class Pai{
public abstract void fun();
}
//紙牌繼承了 牌類, 實現了Magic接口
class Card extends Pai implements Magic{
//牌有炸的方法
public void bang(){
System.out.println("炸了, 翻倍...");
}
public void shunzi(){
System.out.println("順出去,沒了.....");
}
public void fun(){
System.out.println("打牌雖好,不要貪多哦!!!");
}
public void moShu(){
System.out.println("春晚,變魔術.....");
}
}
class MaJiang extends Pai{
public void fun(){
System.out.println("打麻將雖好,四圈差不多了");
}
}
返回值類型爲 類 抽象類 接口
定義方法 修飾符 返回值類型 {
return 返回值
}
類作爲返回值類型,返回的是類的對象
抽象類作爲返回值類型,返回的是抽象類的子類對象
class FaPaiJiTest{
public static void main(String[] args){
//創建人對象
Person p = new Person();
FaPaiJi fpj = p.getFaPaiJi();
//Magic m = fpj.faPai3();
//Magic m = new Person().getFaPaiJi().faPai3(); //鏈式編程
new Person().getFaPaiJi().faPai3().moShu();
}
}
class Person{
//人使用 發牌機工作
public Card work(FaPaiJi fpj ){
Card c = fpj.faPai();
return c ;// Card
}
//人拿到發牌機
public FaPaiJi getFaPaiJi(){
return new FaPaiJi();
}
}
class FaPaiJi {
//發牌機發牌
public Card faPai(){
Card c = new Card();
return c;
}
public Pai faPai2(){
//返回的是抽象類的子類對象
Pai p = new Card(); //多態
return p;
}
public Magic faPai3(){
//返回的是接口的實現類的子類對象
Magic m = new Card(); //多態
return m;
}
}
//定義接口
interface Magic{
public abstract void moShu();
}
//定義牌類
abstract class Pai{
public abstract void fun();
}
//card 繼承牌類 ,實現接口
class Card extends Pai implements Magic{
public void tongHuaShun(){
System.out.println("同花順.....");
}
public void fun(){
System.out.println("玩牌好好玩~~~");
}
public void moShu(){
System.out.println("春晚,變魔術.....");
}
}
-----------android培訓、java培訓、java學習型技術博客、期待與您交流!------------