黑马程序员——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学习型技术博客、期待与您交流!------------

 

你可能感兴趣的:(Java学习笔记)