黑马程序员——面向对象2

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

一、继承

 

1.继承的含义:

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。 多个类可以称为子类,单独这个类称为父类或者超类。

 

2.Java中表示继承的格式:

1)用关键字extends表示

2)格式:class 子类名 extends 父类名 {}

 

3.继承的好处:

1)提高了代码的复用性

2)提高了代码的维护性

3)让类与类产生了一个关系,是多态的前提

 

4.继承的弊端:

1)让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。

原则:低耦合,高内聚。

耦合:类与类的关系

内聚:自己完成某件事情的能力

2)打破了封装性

 

5.Java中继承的特点

1)Java中类只支持单继承

2)Java中可以多层(重)继承(继承体系)

 

6.继承的注意事项:

1) 子类不能继承父类的私有成员

2) 子类不能继承父类的构造方法,但是可以通过super去访问

3) 不要为了部分功能而去继承

 

7.什么时候使用继承呢?

1)继承体现的是:is a的关系。

2)采用假设法

 

8.Java继承中的成员关系

1)成员变量

子类的成员变量名称和父类中的成员变量名称不一样

子类的成员变量名称和父类中的成员变量名称一样,访问方式:

子类的方法访问变量的查找顺序:

在子类方法的局部范围找,有就使用。

在子类的成员范围找,有就使用。

在父类的成员范围找,有就使用。

找不到,就报错。

 

2)构造方法

子类的构造方法默认会去访问父类的无参构造方法,为了子类访问父类数据的初始化

父类中如果没有无参构造方法解决办法:

子类通过super去明确调用带参构造

子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造

让父类提供无参构造

3)成员方法

子类的成员方法和父类中的成员方法名称不一样

子类的成员方法和父类中的成员方法名称一样,通过子类对象访问一个方法的查找顺序:

在子类中找,有就使用

在父类中找,有就使用

找不到,就报错

 

9.猫狗案例的分析和实现

 

packagecom.itheima; 

//定义动物类 

class Animal{ 

// 姓名 

private String name; 

// 年龄 

private int age; 

// 颜色 

private String color; 

 

public Animal() { } 

 

public Animal(String name, int age, String color) { 

      this.name = name; 

      this.age = age; 

      this.color = color; 

 } 

public String getName() { 

        return name; 

   } 

 

    public void setName(String name) { 

        this.name = name; 

   } 

   public int getAge() { 

       return age; 

   } 

 

   public void setAge(int age) { 

     this.age = age; 

   } 

 

   public String getColor() { 

       return color; 

       } 

 

    public void setColor(String color) { 

    this.color = color; 

 } 

 

   public void eat() { 

    System.out.println("吃饭"); 

    } 

    } 

    // 定义猫类 

class Cat extends Animal { 

       public Cat() {  } 

 

public Cat(Stringname, int age, String color) { 

           super(name,age, color); 

       } 

 

public void catchMouse() { 

           System.out.println("抓老鼠"); 

       } 

    } 

     

    // 定义狗类 

    class Dog extends Animal { 

       public Dog() { }

       public Dog(String name, int age, String color) { 

           super(name, age, color); 

       } 

     

        public void lookHome() { 

           System.out.println("看家"); 

       } 

    } 

     

    // 测试类 

    class ExtendsTest5 { 

       public static void main(String[] args) { 

          // 测试猫 

// 方式1 

          Cat c1 = new Cat(); 

           c1.setName("Tom"); 

          c1.setAge(3); 

           c1.setColor("白色"); 

          System.out.println("猫的名字是:" + c1.getName() + ";年龄是:" +c1.getAge()+ ";颜色是:" + c1.getColor()); 

          c1.eat(); 

          c1.catchMouse (); 

          System.out.println("---------------"); 

          // 方式2 

          Cat c2 = new Cat("杰瑞", 5,"土豪金"); 

           System.out.println("猫的名字是:" + c2.getName() + ";年龄是:" + c2.getAge()  +";颜色是:" + c2.getColor()); 

           c2.eat(); 

           c2.catchMouse (); 

        // 测试狗 

       // 方式1 

           Dogd1 = new Dog(); 

           d1.setName("John"); 

          d1.setAge(5); 

          d1.setColor("黑色"); 

           System.out.println("狗的名字是:" + d1.getName() + ";年龄是:" + d1.getAge() + ";颜色是:" +d1.getColor()); 

          d1.eat(); 

           d1.lookDoor(); 

          System.out.println("---------------"); 

        // 方式2 

           Dogd2 = new Dog("Smith", 7, "黄"); 

          System.out.println("狗的名字是:" + d2.getName() + ";年龄是:" +d2.getAge()  + ";颜色是:" + d2.getColor()); 

          d2.eat(); 

          d2.lookDoor(); 

    } 

 

二、多态

 

1.多态的描述:

事物存在的多种形态

 

2.多态的前提:

有继承或者实现关系。

有方法重写。

有父类或者父接口引用指向子类对象。

 

3.多态的分类:

具体类多态

class Fu {}

class Zi extends Fu {}

Fu f = new Zi();

 

抽象类多态

abstract class Fu {}

class Zi extends Fu {}

Fu f = new Zi();

 

接口多态

interface Fu {}

class Zi implements Fu {}

Fu f = new Zi();

 

4.多态中的成员访问特点

成员变量:编译看左边,运行看左边

构造方法:子类的构造都会默认访问父类构造

成员方法:编译看左边,运行看右边

静态方法:编译看左边,运行看左边

 

5.多态的好处与弊端:

1)好处:

提高代码的维护性(继承体现)

提高代码的扩展性(多态体现)

2)弊端:

父不能使用子的特有功能。现象:子可以当作父使用,父不能当作子使用。

 

6.多态中的转型

向上转型:从子到父

向下转型:从父到子

 

7.猫狗案例

 

/*

    猫狗案例

 */ 

class Animal { 

    public void eat() { 

       System.out.println("吃饭"); 

    } 

 

class Dog extends Animal { 

    public voideat() { 

       System.out.println("狗吃肉"); 

    } 

 

    public voidlookHome() { 

       System.out.println("狗看门"); 

    } 

 

class Cat extends Animal { 

    public voideat() { 

       System.out.println("猫吃鱼"); 

    } 

 

    public void catchMouse(){ 

       System.out.println("捉老鼠"); 

    } 

 

class DuoTaiTest { 

    public staticvoid main(String[] args) { 

        // 定义为狗 

        Animal a =new Dog(); 

       a.eat(); 

       System.out.println("--------------"); 

        // 还原成狗 

        Dog d =(Dog) a; 

       d.eat(); 

       d.lookDoor(); 

       System.out.println("--------------"); 

        // 变成猫 

        a = newCat(); 

       a.eat(); 

       System.out.println("--------------"); 

        // 还原成猫 

        Cat c =(Cat) a; 

       c.eat(); 

        c.catchMouse(); 

       System.out.println("--------------"); 

 

        // 演示错误的内容 

        // Dog dd =new Animal(); 

        // Dog ddd= new Cat(); 

        //ClassCastException 

        // Dog dd =(Dog)a; 

    } 

 

三、抽象类

 

1.为什么用抽象类:

在定义方法声明一样,但是每个具体的对象在具体实现的时候内容不一样的共性方法的时,则不能给出具体的方法体。

而一个没有具体的方法体的方法是抽象的方法。在一个类中如果有抽象方法,该类必须定义为抽象类。

 

2.抽象类的特点:

抽象类和抽象方法必须用关键字abstract修饰

抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类

抽象类不能实例化

抽象类的子类:

是一个抽象类。

是一个具体类。这个类必须重写抽象类中的所有抽象方法。

 

3.抽象类的成员特点:

成员变量:有变量,有常量

构造方法:有构造方法

成员方法:有抽象,有非抽象

 

4.抽象类的几个小问题

1)抽象类有构造方法,不能实例化,那么构造方法有什么用?

用于子类访问父类数据的初始化

2)一个类如果没有抽象方法,却定义为了抽象类,有什么用?

为了不让创建对象

3)abstract不能和哪些关键字共存

final 冲突

private 冲突

static 无意义

 

5.猫狗案例

/*

    猫狗案例

        具体事物:猫,狗

        共性:姓名,年龄,吃饭

 

    分析:从具体到抽象

        猫:

            成员变量:姓名,年龄

            构造方法:无参,带参

            成员方法:吃饭(猫吃鱼)

            

        狗:

            成员变量:姓名,年龄

            构造方法:无参,带参

            成员方法:吃饭(狗吃肉)

            

        因为有共性的内容,所以就提取了一个父类。动物。

        但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,

        而方法是抽象的类,类就必须定义为抽象类。

        

        抽象动物类:

            成员变量:姓名,年龄

            构造方法:无参,带参

            成员方法:吃饭();

    

    实现:从抽象到具体

        动物类:

            成员变量:姓名,年龄

            构造方法:无参,带参

            成员方法:吃饭();

            

        狗类:

            继承自动物类

            重写吃饭();

            

        猫类:

            继承自动物类

            重写吃饭();

 */ 

//定义抽象的动物类 

abstract class Animal { 

    // 姓名 

    private Stringname; 

    // 年龄 

    private intage; 

 

    public Animal(){ 

    } 

 

    publicAnimal(String name, int age) { 

        this.name =name; 

        this.age =age; 

    } 

 

    public StringgetName() { 

        returnname; 

    } 

 

    public voidsetName(String name) { 

        this.name = name; 

    } 

 

    public intgetAge() { 

        returnage; 

    } 

 

    public voidsetAge(int age) { 

        this.age =age; 

    } 

 

    // 定义一个抽象方法 

    public abstractvoid eat(); 

 

// 定义具体的狗类 

class Dog extends Animal { 

    public Dog(){ 

    } 

 

    publicDog(String name, int age) { 

        super(name,age); 

    } 

 

    public voideat() { 

       System.out.println("狗吃肉"); 

    } 

 

// 定义具体的猫类 

class Cat extends Animal { 

    public Cat(){ 

    } 

 

    publicCat(String name, int age) { 

        super(name,age); 

    } 

 

    public voideat() { 

       System.out.println("猫吃鱼"); 

    } 

 

// 测试类 

class AbstractTest { 

    public staticvoid main(String[] args) { 

        // 测试狗类 

        // 具体类用法 

        // 方式1: 

        Dog d = newDog(); 

       d.setName("旺财"); 

       d.setAge(3); 

       System.out.println(d.getName() + "---" + d.getAge()); 

        d.eat(); 

        // 方式2: 

        Dog d2 =new Dog("旺财", 3); 

       System.out.println(d2.getName() + "---" + d2.getAge()); 

       d2.eat(); 

       System.out.println("---------------------------"); 

 

        Animal a =new Dog(); 

        a.setName("旺财"); 

       a.setAge(3); 

       System.out.println(a.getName() + "---" + a.getAge()); 

       a.eat(); 

 

        Animal a2 =new Dog("旺财", 3); 

       System.out.println(a2.getName() + "---" + a2.getAge()); 

       a2.eat(); 

 

        // 测试猫类 

        // 具体类用法 

        // 方式1: 

        Cat c = newCat(); 

       c.setName("喵喵"); 

       c.setAge(4); 

       System.out.println(c.getName() + "---" + c.getAge()); 

       c.eat(); 

        // 方式2: 

        Cat c2 =new Cat("喵喵", 4); 

       System.out.println(c2.getName() + "---" + c2.getAge()); 

       c2.eat(); 

       System.out.println("---------------------------"); 

 

        Animal b =new Cat(); 

       b.setName("喵喵"); 

        b.setAge(4); 

       System.out.println(b.getName() + "---" + b.getAge()); 

       b.eat(); 

 

        Animal b2 =new Cat("喵喵", 4); 

       System.out.println(b2.getName() + "---" + b2.getAge()); 

       b2.eat(); 

    } 

 

四、接口

 

1.接口概述:

从狭义的角度讲就是指java中的interface
从广义的角度讲对外提供规则的都是接口 

2.接口的特点:

接口用关键字interface修饰:interface 接口名 {}

类实现接口用implements修饰:class 类名 implements 接口名 {}

接口不能实例化

接口的实现类:

是一个抽象类。

是一个具体类,这个类必须重写接口中的所有抽象方法。

 

3.接口的成员特点:

成员变量,只能是常量,默认修饰符:public static final

没有构造方法

成员方法,只能是抽象的,默认修饰符:public abstract

 

4.类与接口之间的关系:

类与类:继承关系,只能单继承,可以多层继承

类与接口:实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时,实现多个接口

接口与接口:继承关系,可以单继承,也可以多继承

 

5.抽象类和接口的区别:

成员区别

抽象类:可以是常量也可以是变量

接口:只能是常量

关系区别:

类与类:继承

类与接口:实现关系,可以单实现,也可以多实现。

接口与接口:继承关系,可以单继承,也可以多继承

设计理念不同

抽象类:is a,抽象类中定义的是共性功能。

接口:like a,接口中定义的是扩展功能。

 

6.猫狗案例

/*

    猫狗案例,加入跳高的额外功能

    分析:从具体到抽象

        猫:

            姓名,年龄

            吃饭,睡觉

        狗:

            姓名,年龄

            吃饭,睡觉

            

        由于有共性功能,所以,我们抽取出一个父类:

        动物:

            姓名,年龄

            吃饭();

            睡觉(){}

            

        猫:继承自动物

        狗:继承自动物

        

        跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口

        接口:

            跳高

            

        部分猫:实现跳高

        部分狗:实现跳高

    实现;

        从抽象到具体

        

    使用:

        使用具体类

 */ 

//定义跳高接口 

interface Jumpping { 

    // 跳高功能 

    public abstractvoid jump(); 

 

// 定义抽象类 

abstract class Animal { 

    // 姓名 

    private Stringname; 

    // 年龄 

    private intage; 

 

    public Animal(){ 

    } 

 

    publicAnimal(String name, int age) { 

        this.name =name; 

        this.age =age; 

    } 

 

    public StringgetName() { 

        returnname; 

    } 

 

    public voidsetName(String name) { 

        this.name = name; 

    } 

 

    public intgetAge() { 

        returnage; 

    } 

 

    public voidsetAge(int age) { 

        this.age =age; 

    } 

 

    // 吃饭(); 

    public abstractvoid eat(); 

 

    // 睡觉(){} 

    public voidsleep() { 

       System.out.println("睡觉觉了"); 

    } 

 

// 具体猫类 

class Cat extends Animal { 

    public Cat(){ 

    } 

 

    publicCat(String name, int age) { 

        super(name,age); 

    } 

 

    public voideat() {  

       System.out.println("猫吃鱼"); 

    } 

 

// 具体狗类 

class Dog extends Animal { 

    public Dog(){ 

    } 

 

    publicDog(String name, int age) { 

        super(name,age); 

    } 

 

    public voideat() { 

       System.out.println("狗吃肉"); 

    } 

 

// 有跳高功能的猫 

class JumpCat extends Cat implements Jumpping { 

    publicJumpCat() { 

    } 

 

    publicJumpCat(String name, int age) { 

        super(name,age); 

    } 

 

    public voidjump() { 

       System.out.println("跳高猫"); 

    } 

 

// 有跳高功能的狗 

class JumpDog extends Dog implements Jumpping { 

    publicJumpDog() { 

    } 

 

    publicJumpDog(String name, int age) { 

        super(name,age); 

    } 

 

    public voidjump() { 

       System.out.println("跳高狗"); 

    } 

 

class InterfaceTest { 

    public staticvoid main(String[] args) { 

        // 定义跳高猫并测试 

        JumpCat jc= new JumpCat(); 

       jc.setName("哆啦A梦"); 

       jc.setAge(3); 

       System.out.println(jc.getName() + "---" + jc.getAge()); 

       jc.eat(); 

       jc.sleep(); 

       jc.jump(); 

       System.out.println("-----------------"); 

 

        JumpCat jc2= new JumpCat("加菲猫",2); 

       System.out.println(jc2.getName() + "---" + jc2.getAge()); 

       jc2.eat(); 

       jc2.sleep(); 

       jc2.jump(); 

    } 

 

五、内部类

 

1.内部类的定义:

把类定义在另一个类的内部,该类就被称为内部类。例如:把类B定义在类A中,类B就被称为内部类。

 

2.内部类的访问规则

可以直接访问外部类的成员,包括私有

外部类要想访问内部类成员,必须创建对象

 

3.内部类的分类

成员内部类

private 为了数据的安全性

static 为了访问的方便性

成员内部类不是静态的:

外部类名.内部类名  对象名 = new 外部类名.new 内部类名();

成员内部类是静态的:

外部类名.内部类名  对象名 = new 外部类名.内部类名();

局部内部类

局部内部类访问局部变量必须加final修饰。因为局部变量使用完毕就消失,而堆内存的数据并不会立即消失。所以,堆内存还是用该变量,而改变量已经没有了。

为了让该值还存在,就加final修饰。通过反编译工具我们看到了,加入final后,堆内存直接存储的是值,而不是变量名。

 

4.匿名内部类

是局部内部类的简化形式

前提存在一个类或者接口

格式:

new 类名或者接口名() { 

    重写方法; 

 

本质:其实是继承该类或者实现接口的子类匿名对象

 

5.匿名内部类在开发中的使用

在开发的时候,会看到抽象类,或者接口作为参数。而这个时候,我们知道实际需要的是一个子类对象。

如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。

interface Person { 

   public abstract void study(); 

 

class PersonDemo { 

   public void method(Person p) { 

       p.study(); 

   } 

 

class PersonTest { 

   public static void main(String[] args) { 

       PersonDemo pd = new PersonDemo(); 

       pd.method(new Person() { 

           public void study() { 

                System.out.println("好好学习,天天向上"); 

           } 

       }); 

   } 

}  

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——

你可能感兴趣的:(黑马程序员——面向对象2)