java面向对象(3)

87


一、继承

1.继承的描述

  • 继承是面向对象程序设计不可缺少的设计思想

  • 当一个类没有显示继承其他类的时候,此时这个类默认继承Object,Object类是java中所有类的基类(父类 超类)

public class Animal extends Object
  • 用 extends 关键字表示继承关系

  • JAVA不支持多继承,一个类只能继承一个父类

  • 子类可以调用父类的所有非私有属性和非私有方法

public class Dog  extends Animal{
     public  Dog(){
         super();
         System.out.println("Dog无参构造");
     }
     public Dog(String name){
         super();
         System.out.println("Dog有参构造");
     }
}

2.继承的优点

提高代码的重用性,可扩展性

那么什么时候使用继承呢?

符合is-a关系的设计(xxx是xxx)
将子类共有的属性和行为放到父类中

3.继承的形式和传递性

  • [访问权限修饰符][修饰符] 子类名 extends 父类名{子类体}

  • C类从B类继承,B类又从A类继承,那么C类就具有B类和A类的所有非私有属性和非私有方法。

public class Animal{ 
       public void eat(){} 
}
public class Dog extends Animal{
       public void play(){} 
}
public class XiaoTianQuan extends Dog {
       public void  thinking(){}
}

//子类对象可以直接调用父类的方法,强调复用性 
Dog dog = new Dog (); 
    dog.eat();

4.继承中的构造方法

  • 子类构造方法总是先调用父类构造方法,默认情况下,先调用父类的无参构造方法。

  • 可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法。如果用super,必须写在构造方法的第一行。

  • 如果子类的构造方法中没有显式调用基类构造方法,则默认调用基类无参数的构造方法。

 public  Dog(){
         super();
         System.out.println("Dog无参构造");
     }
     public Dog(String name){
         super();
         System.out.println("Dog有参构造");
     }

5.supper关键字

super();

  1. 表示在子类构造方法中调用父类的构造方法
  2. super语句只能出现在子类构造方法体的第一行
  3. 用“super.成员变量名”来引用父类成员变量
  4. 用“super.方法名(参数列表)”的方式访问父类的方法

6.方法重写

a.构造方法,静态方法不能重写,成员变量不存在重写。

b.当父类中的实现方法(代码)不能满足子类需求时,可以在子类中对父类的方法进行重写。

c.方法重写规则:

(1)方法名相同、参数列表相同
(2)返回值类型相同
(3)访问权限不能小于父类权限

 @Override  //测试子类继承父类重写方法的格式是否一致 编译期间对语法进行校验 
     public void eat() {
        super.eat();  //调用父类的实现
        System.out.println("小狗吃饭");
    }

    @Override
    public void sleep() {
        super.sleep();
        System.out.println("小狗睡觉");
    }

二、抽象类

抽象方法

  • 是一种特殊的方法:它只有声明,没有具体的实现

  • 必须用 abstract 关键字进行修饰

  • 除了不能实例化对象之外,类的其它功能依然存在(成员变量、成员方法和构造方法)

如果一个类中没有包含足够的信息(抽象方法)来描绘一个具体的对象,这样的类就是抽象类。

抽象类中可以没有抽象方法,但是有抽象方法的一定是抽象类。

public abstract class Animal {
    /*
    * 一个抽象类不一定有抽象方法
    * 有抽象方法必然是抽象类
    * 一般用在体系结构的顶层用来进行功能的定义声明
    */

    int num=10;

    /*
       抽象类可以拥有构造方法,但是不能创建对象
    */
    public Animal(){
         System.out.println("Animal无参构造");
    }
     
    /*
    抽象方法:只有方法声明, 没有方法体,也就是没有具体的实现
    */
    public abstract void sleep();//在比较顶级的类中就可以定义一个方法
    }

    public void eat(){
        System.out.println("动物吃");
    }

一个类如果继承了抽象类,那就只有两个选择,一是重写抽象类中所有的抽象方法,二是将该类也定义为抽象类。

//public abstract class Dog extends Animal {
public  class Dog extends Animal {

    public  Dog(){
        super();
    }

    @Override
    public void eat() {
        System.out.println("狗吃东西");
    }
}

抽象类只能用作基类,表示的是一种继承关系。

继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。

否则,该类也必须声明为抽象类。


三、多态

1.多态

封装:包装

继承:子继承父

多态:同一事物,在不同时刻,表现出的不同的状态。

2.多态存在的必要条件

  • 子类继承父类 (还包括接口的实现)(前提条件)

  • 子类重写父类的方法(前提条件)

  • 父类引用指向子类对象

public abstract class Animal {

     int num=10;

     public abstract void  eat();

     public static void sleep(){
         System.out.println("睡觉");
     }

}
public  class Dog  extends Animal{

    int num = 20;

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    public static void sleep(){
        System.out.println("狗睡觉");
    }

}
public class Cat  extends Animal{

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

}

多态访问类中的成员方法:

编译期间调用父类的方法,运行时则执行子类中的方法

public class Test{

    public static void main(String[] args) {

         Dog dog =  new Dog();

         Animal d = new Dog();//Animal的引用指向Dog的对象
                d.eat();//调用的是子类中的方法
                /* 简称:编译看左边,运行看右边 */
                
                d.sleep();//对于静态方法编译和运行都看左边
        System.out.println(d.num);//对于成员变量编译和运行都看左边

                d = new Cat();
                d.eat();
    }
}

四、final关键字

“final” 用于修饰类,属性(成员变量—>常量),方法。

1.修饰类

修饰的类不能被其他的类继承

public final class FinlDemo {
   //final修饰类
}

2.修饰属性

修饰后的属性使用前必须赋值,并且赋予的值不能改变

public  class FinlDemo {

       static final int PI = 3;
       //final修饰属性:直接为常量赋值,建议使用static修饰,这样在内存中就只有一份,所有对象共享。
       
        final int num;
        //不用static修饰,不需要赋初值,每个对象中都会包含一个常量,在构造方法中初始化。

        public FinlDemo(int n) {
            num = n;
        }

        public final static void test(final int a){
       // a=10;   被final修饰不能再改变数值
           System.out.println(a);
        }
}

3.修饰方法

修饰的方法不能被重写

  public final static void  test(final  int a){
      //修饰方法参数,当调用时传入值后,值不能改变
      //在方法参数前面加final关键字,为了防止数据在方法体中被修改。
  }

4.运行

public static void main(String[] args) {
        FinlDemo f1 = new FinlDemo(10);
        FinlDemo f2 = new FinlDemo(20);
        System.out.println(f1.num);
        System.out.println(f2.num);

         test(10);
         test(20);

    }

五、接口

1.生活中的接口

在这里插入图片描述

2.接口的特征

  • 接口不能被实例化

  • 实现类必须重写接口的所有方法

  • 实现类可以实现多个接口

  • 接口中的变量都是静态常量

接口存在的意义:java中一个类只能有一个父类,所以用接口可以实现多继承的逻辑。

从本质上讲,接口就是一种特殊的抽象类,这种抽象类只包含常量和方法的定义,而没有变量和方法的实现。

3.接口的定义和使用

(1) 先建立三个接口 A,B,C

public interface InterfaceA {

       void drink();
}
public interface InterfaceB {

     void play();
}

(2) 建立一个新的接口 “MyInerface” 来继承接口 A,B

public interface MyInerface extends InterfaceA,InterfaceB{
/*
   1、接口类似于抽象类,作为功能的定义而存在
   2、接口比抽象更彻底一些
   3、接口可以继承多个接口
   4、接口是用来被其他类实现
   5、定义 静态常量,抽象方法,默认方法,静态方法
*/

    //public static final int num = 10;  接口中声明的属性默认为 public static final
       int NUM = 10;//静态常量

    //public abstract void eat();
      void eat();//定义方法(定义功能)
      void sleep();

     /*
      通过子类调用, 默认方法子类可以重写,也可以不重写
      */
     default void test(){
          System.out.println("默认方法");
     }

      //静态可以直接通过接口名调用
      static void test1(){
          System.out.println("静态方法");
      }

}

(3)建立 “MyInterfaceImpl” 继承 “MyInerface” 和 C

/*
一个类要实现接口
   要么将此类声明为抽象类
   要么重写所有抽象方法,可以重写默认方法,也可以不重写
*/


//一个类可以直接继承一个类
//一个类可以实现多个接口

//public abstract class MyInterfaceImpl implements MyInerface{  接口是隐式抽象的,当声明一个接口的时候,可以不使用abstract关键字

public  class MyInterfaceImpl extends Object implements MyInerface,InterfaceC{

        @Override
        public void eat() {
            System.out.println("MyInterfaceImpl--eat");
        }
        @Override
        public void sleep() {
            System.out.println("MyInterfaceImpl--sleep");
        }

        @Override
        public void drink() {

        }

        @Override
        public void play() {

       }

        @Override
        public void work() {

        }

        @Override
        public void test() {
            System.out.println("MyInterfaceImpl--test");
        }
}

(4)测试代码

public class Test {

    public static void main(String[] args) {

        System.out.println(MyInerface.NUM);
        MyInerface.test1();

    }
}

4.接口的特性

  • 接口是隐式抽象的,当声明一个接口的时候,可以不使用abstract关键字

  • 接口中方法可以是抽象的,静态的,默认的

  • 接口中声明的属性默认为 public static final

  • 接口不是被类继承了,而是被类实现了

  • 接口不能实例化对象(无构造方法),但可以声明对象的引用。(多态 性)

  • 多个类可以实现同一个接口

  • 一个类可以实现多个接口,但只能继承一个类

  • 与继承关系类似,接口与实现类之间存在多态性

  • 一个接口能继承其它多个接口

  • 当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值