Java——面向对象(三)

面向对象语言的三大特征:

                                     封装、继承、多态

目录

1. 面向对象的特征——封装

2. 面向对象的特征——继承

2.1 继承

 2.2 继承的构造方法

2.3 方法的重写

3. 抽象类(abstract)

4. 面向对象的特征——多态

4.1 定义

4.2 条件

4.3 多态优缺点

4.4 instanceof

5. final关键字

6. 接口

6.1 interfance

6.2 implements

附加:接口和抽象类的区别 


1. 面向对象的特征——封装

定义:将类的某些信息隐藏起来(访问权限修饰符),不让在外部直接对其访问,可以通过一个特定的方法,来对隐藏的信息进行访问,便于访问。

例1:

public class Student {
    private  String name;//隐藏类的属性
    private  int age;
    public Student(){

    }
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setName("张三");
        System.out.println(stu.getName());
        stu.setAge(16);
        System.out.println(stu.getAge());
    }
}

例2:

设计模式:解决某一类问题的解决方案(模式)

单例模式 ---> 让一个类在一个程序,只能创建一个对象。

public class studentDao {
    private static studentDao stu = null;
    private studentDao(){

    }
//将构造方法私有化,在其他类中不能随便使用
    public static studentDao getStu(){
        if(stu == null){
            stu = new studentDao();
            return stu;
        }
        return stu;
    }

    public static void main(String[] args) {
        System.out.println(studentDao.getStu());
        System.out.println(studentDao.getStu());

    }
}

2. 面向对象的特征——继承

2.1 继承

定义:子继承父,实现代码的重用,提高代码的可扩展性。

什么清空下使用继承?

是用一类,什么是什么,is-a关系

将子类的共有的属性和方法

语法:[ 访问权限修饰符][修饰符] 子类名  extends  父类名{  }

名词:父类(基类)         子类(派生类)

继承的传递性

C类继承B类,B类继承A类,C类继承B、C类中非私有的属性和方法。

使用extends 关键字

一个类只能直接继承一个父类,继承后子类就可以使用父类中非私有的成员方法和属性,

在子类中可以扩展子类特有的属性和方法。

//当一个类中没有显示的继承某个类,那么这个类默认继承object类,object这个类是所有类的基类
//public class Animal extends Object{}
public class Animal{
    //成员变量
    private String name;
    private int age;
    //构造方法
    public Animal(){
      
    }
    //访问私有成员属性的入口
    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 void eat(){
        System.out.println(name + "吃东西");
    }
}
public class Panda extends Animal{
    public Panda(){
       
    }
    public void eat(){
        System.out.println("构造方法");
        super.eat();
    }
    public void play(){
        System.out.println("功夫熊猫");
    }
}
public class Yu extends Panda{
    public Yu(){
        
    }
    
    public void KongFu(){
        System.out.println("鱼鱼是只会耍双节棍的熊猫");
    }

}
public class Test {
    public static void main(String[] args) {
        //调用父类的非私有方法
        Dog dog = new Dog();
        dog.setName("小段");
        dog.setAge(5);
        dog.eat();
        System.out.println(dog.getName());
        System.out.println(dog.getAge());
        //调用父类的非私有方法
        Panda panda = new Panda();
        panda.setName("食铁兽");
        panda.setAge(7);
        panda.eat();
        //子类特有的方法
        panda.play();

        //继承具有传递性 C继承B,B继承A  C类具有B、A类中的非私有的属性和方法。
        Yu yu = new Yu();
        yu.setAge(5);
        yu.setName("鱼鱼");
        System.out.println(yu.getName());
        System.out.println(yu.getAge());
        yu.eat();
        //调用父类
        yu.play();
        //调用父类的父类
        yu.KongFu();
    }
/*
小段吃东西
小段
5
构造方法
食铁兽吃东西
功夫熊猫
鱼鱼
5
构造方法
鱼鱼吃东西
功夫熊猫
鱼鱼是只会耍双节棍的熊猫
        */
}

 2.2 继承的构造方法

在创建一个子类对象后,调用构造方法时,从上向下调用,先初始化父类信息

使用super() 在子类构造方法的第一行默认执行,调用父类无参的构造方法。

super() 表示调用父类中无参构造,默认存在的,必须放在第一行。

public class Animal extends Object{
    private String name;
    private int age;
    public Animal(){
        super();
        System.out.println("animal类的无参构造方法");
    }
    public Animal(int age){
        this.age = age;
        System.out.println("Animal类的有参构造方法");
    }
    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 void eat(){
        System.out.println(name + "吃东西");
    }
}
public class Panda extends Animal{
    public Panda(){
        super();
        System.out.println("Panda类的无参构造方法");
    }
    public Panda(int age){
        super(age);
        System.out.println("Panda类的有参构造方法");
    }
    @Override
    public void eat(){
        System.out.println("熊猫抱着竹子吃");

    }
    public void play(){
        System.out.println("功夫熊猫 : 呼呼哈嘿");
        super.eat();
    }
}
public class Yu extends Panda{
    public Yu(){
        super();
        System.out.println("Yu的无参构造方法");
    }
    public Yu(int age){
        super(age);
        System.out.println("Yu的有参构造方法");
    }
    public void KongFu(){
        System.out.println("鱼鱼是只会耍双节棍的熊猫");
    }

}
public class Test1 {
    public static void main(String[] args) {
        Yu yu1= new Yu(5);
        //继承具有传递性 C继承B,B继承A  C类具有B、A类中的非私有的属性和方法。
        Yu yu = new Yu();
        yu.setAge(5);
        yu.setName("小鱼儿");

        System.out.println(yu.getName());
        System.out.println(yu.getAge());
        yu.eat();
        //调用父类
        yu.play();
        //调用父类的父类
        yu.KongFu();

    }
}

 

2.3 方法的重写

原因:当父类的方法实现不能满足子类需求时,需要进行重写

方式:在子类中对父类中的方法进行重写

规则:

  • 方法名相同
  • 参数列表相同
  • 返回值类型相同
  • 访问权限修饰符不能等于或者大于父类的权限
  • 声明异常类型等于或小于父类所声明的异常类型(子类和父类异常类型之间有从属关系)

@override  Java中提供的一个注解标签(一种标记)

添加此注解的标签表示此方法是从父类重写过来的,就会对其进行语法验证。

注:@overload(重载)

public class Animal extends Object{
    private String name;
    private int age;
    public Animal(){
    }
    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 void eat(){
        System.out.println(name + "吃东西");
    }
}
public class Panda extends Animal{
    public Panda(){
    }
    @Override    //Java中提供的一个注解标签(一种标记)
    public void eat(){
        System.out.println("熊猫抱着竹子吃");

    }
    public void play(){
        System.out.println("功夫熊猫 : 呼呼哈嘿");
        super.eat();
    }
}
public class Yu extends Panda{
    public Yu(){
    }
    public void KongFu(){
        System.out.println("鱼鱼是只会耍双节棍的熊猫");
    }

}
public class Test2 {
    public static void main(String[] args) {
        Yu yu = new Yu();
        yu.setName("小鱼儿");
        yu.setAge(1);
        yu.eat();
        yu.play();
        /*
          熊猫抱着竹子吃
         功夫熊猫 : 呼呼哈嘿
         小鱼儿吃东西
         */
    }
}

3. 抽象类(abstract)

抽象类:也是类,抽象(概念)

抽象方法:

定义:一种特殊的方法。只有声明,没有实现。

在一些比较靠顶层的类,它的实现与子类大多数不同,此时没有必要在顶层类实现,只需要声明功能即可。

Person{

      //定义一个吃饭的方法即可,不需要实现。

      public abstract  void eat();

}

         abstract 修饰的方法是抽象方法,没有方法体。

        抽象类abstract修饰抽象类可能包含了抽象方法,也可能不包含抽象方法。

        如果一个类中没有包含足够的信息,来描绘一个具体的对象,这样的类就是抽象类。抽象类不能创建对象(因为其中包含抽样方法),其他功能与类相同(成员变量、成员方法、构造方法)

        如果某个类中包含有抽象方法,那么该类必须定义成抽象类。

         抽象类一般都是位于体系结构的上层,用来定义功能

public abstract class Person {
//非静态成员变量
    String name = "小明";
//成员方法
    public void eat(){
        System.out.println(name + "爱吃饭");
    }
    //抽象方法
/*
          在一些比较靠顶层的类,它的实现与子类大多数不同,此时没必要在顶层类实现.只需要声明功能
          abstract 修饰的方法是抽象方法,没有方法体
   */
    public abstract void Work();
    //静态成员方法
    public static void speak(){
        System.out.println("讲话");
    }

}
public class Duan extends Person{
    //在顶层进行定义,在底层进行实现
    //抽象类一般都是位于抽象类一般都是位于体系结构的上层,用来定义功能
    //如果一个类继承了抽象类,要么重写抽象类类中的所有抽象方法;要么将此类设置为抽象类 
    //public abstract class Chinese extends Person{}
   //重写
    @Override
    public void Work() {
        System.out.println(name + "热爱生活");
    }
}
public class Test {
    public static void main(String[] args) {
        Person person = new Duan();
        
        person.name = "小宇";
        person.eat();
        person.Work();
        person.speak();
        
    }
}

特点:

  • 抽象类不能被实例化,但可以有构造方法,因为抽象类中含有无具体实现的方法, 所以不能用

        抽象类创建对象。

  •  抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实 现其中的所有

       抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一 样。否则,该类也必须声明

        为抽象类。

  • 使用关键字abstract定义抽象类

如果一个类继承了抽象类,要么重写抽象类类中的所有抽象方法;要么将此类设置为抽象类

4. 面向对象的特征——多态

4.1 定义

    在同一种事物中,在不同时该表现不同的状态

4.2 条件

  1.  要有继承(包括接口)(前提条件)

       类继承类、类继承抽象类、类实现接口

   2.  要用重新(前提条件)

   3.  父类引用指向子类对象

        例:Animal 父类              Dog     子类      eat()是在子类中重写抽象类

                Animl  animal =  new Dog(); 

              animal.eat();

              编译期间:animal 的类型是animal类,调用的是抽象的eat();

              运行期间:animal 指向的是一个Dog对象,运行的是Dog中重写的eat();

针对非静态成员变量:编译期间在左边,运行期间看右边。

针对静态方法、针对成员变量:编译期间和运行期间都看左边。

public class Test {
    public static void main(String[] args) {
        /*
         父类的引用指向子类的对象
        */
        Person p = new Duan();
       
          /*
             编译期间  p.Work() p的类型是Animal类,调用的是抽象的Work()
             运行期间  p执向的是一个Duan对象,运行的是Duan中重写的Work()

             针对于非静态成员方法:
               编译期间看左边(写代码时)
               运行期间看右边
           */
                 p.Work();
                 p.eat();

          /*
              针对静态方法
                编译期间看左边
                运行期间还是看左边
           */
                 p.speak();
        /*
          针对成员变量
               编译期间看左边
               运行期间还是看左边
         */
        System.out.println(p.name);

    }
}

4.3 多态优缺点

优点:父类引用子类对象,提高程序的可扩展性。

缺点:父类类型中不能调用子类特有的方法。

多态转型

自动转型:子继承父

   向上转型:子类型自动上升为父类型

  Animal dog = new Dog();

强制转换

   向下转型: 父类型转为子类子类自己的类型。

例:animal 为父类  Cat,Dog子类   play() 为Dog中的方法。

public class Test{
    public static void main(String[] args) {
        Animal dog = new Dog();
        Cat cat = new Cat();
         Test t = new Test();
         t.makeCry(dog);
         t.makeCry(cat);
    }
   public void makeCry(Animal animal){
        animal.play();
        if(animal instanceof Dog){
            Dog dog = (Dog)animal; 
        }
   }

}
//结果:
//狗玩
//猫玩

4.4 instanceof

判断animal中实际传入的类型是什么
父类引用  instanceof 具体的子类类型
instanceof 判断父类引用实际表示的对象  是不是 指定类型 

5. final关键字

final 用于声明属性,方法和类。

修饰类:该类不能被其他类继承

修饰方法:修饰的方法不能被重写

修饰属性:修饰后的属性是常量,创建时需要对其赋值,且赋值后值不能改变。

(1) static final int num = 10;

         在定义之初就为其进行赋值,那么所有对象不能改变其值,用static 修饰

(2) final int num;

        public Animal(int num){

                this.num = num;

        }

   在定义之初没有为其赋值,必须在构造方法中为其赋值

    public class Dog extends Animal{

           public Dog(){

                 super(10);

           }
     }

属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期都不能 修改。 

方法:子类里不可以重写

 类:不能被定义为抽象类或是接口,不可被继承

6. 接口

6.1 interfance

修饰的是接口

生活中,如USB接口  规范的定义(定义接口的大小,如何传输数据等)

[访问修饰符] interface 接口名称 [extends 其他的接口名1,….其他的接口名n] { // 声明常量 抽象方法 静态方法 默认方法 }

接口类似于抽象类(可以看做是一个更加彻底的抽象类)

接口和抽象类都是用于在顶层类,指定规范(设计功能)

特点:没有构造方法,不能创建方法,不能实例化对象。

           接口名只能调用接口中静态的

           接口也表示抽象(功能设计),也需要其他类来实现的(继承)

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

           类和接口:

           一个接口 可以 继承多个接口

           一个类可以实现多个接口

           一个类只能直接继承一个类

注:jdk8之前 接口只能定义 静态常量 和 抽象方法;
       jdk8之后 接口增加了静态方法  默认方法

public interface Animal {
    //public static final   int num = 10;
    //接口中的成员变量默认是 静态常量
    public static final int num = 10;
    //public abstract   void eat();
    //接口定义抽象方法
    public void eat();
    //静态方法  直接通过接口名调用
    public static void play(){
        System.out.println("动物玩static");
    }
    //默认 通过子类对象调用
    public default void sleep(){
        System.out.println("动物睡default");
    }
}

6.2 implements

在子类对接口进行实现

[访问修饰符] class 类名 implements 接口名1,接口名2……{}

结合继承:

[访问修饰符] class 类名 extends 父类名 implements 接口名1,接口名2……{}

例:public abstract class Dog  implements Animal{}

//public abstract class Cat  implements Animal{}
public class Cat implements Animal{
    @Override
    public void eat() {
        System.out.println("小段吃烤鱼");
    }
}
public class Dog implements Animal{

    @Override
    public void eat() {
        System.out.println("小宇吃烤肉");
    }
}

注:在测试类中,接口名只能调用接口中静态的成员 

public class Test {

    public static void main(String[] args) {
         /*
          接口名只能调用接口中静态的成员
         */
        System.out.println(Animal.num);
        int num = Animal.num;
        Animal.play();
        Animal dog = new Dog();
        Animal cat = new Cat();
        Test test = new Test();
        test.AnimalEat(dog);
        test.AnimalEat(cat);

    }
    public void AnimalEat(Animal animal){
        animal.eat();
    }

}

附加:接口和抽象类的区别 

抽象类和接口的区别
                     抽象类                               接口
关键字abstract关键字interface
可以包含成员方法抽象方法,静态方法和默认方法(加default)
成员变量可以是各种类型的成员变量只能是 public static final 类型的,并且必须赋值
一个类只能继承一个抽象类一个类却可以实现多个接口
可以包含初始化块不能包含初始化块
public 、protected、default这些修饰符接口只能是public abstract方法
抽象类继承的关键字extends接口的实现关键字implements
抽象类可以包含构造方法,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器完成属于抽象类的初始化操作接口不能包含构造方法

相同点:

(1) 都不能被实例化

(2) 都可以包含方法声明

(3) 子类( 派生类)必须实现未实现的方法


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值