黑馬程序員——Java基礎---面向對象2

-----------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. superthis 必須在第一行,並且只能有一個 

演示用例:

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

 

輸出完成 (耗時 ) - 正常終止

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{//定義馬戲貓類繼承貓類並實現TrainNature接口

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學習型技術博客、期待與您交流!------------

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章