面向对象的三大特性

面向对象三大特性(封装、继承、多态)

封装

使用private修饰符对属性进行修饰,限制属性的访方问权限,只有类内部能够访问这样的属性,其它的类通过对象属性的方式是无法访问的。从而对对象的状态(数据)进行保护,外部类要访问的话需要通过调用gt/Set的方法,保证属性统一访问。

  • 学生类Student

    有一些属性都是用private修饰

    提供set,get方法访问这些属性,在调用set的时候可以限制赋值的内容,在调用get的时候可以返回指定的数据,转换和限制的逻辑封装在类的方法中

    //private 就是私有修饰符
    private String name;
    private int sex;
    private int age;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getSex() {
        String result = sex == 1 ? "男" : "女";
        return result;
    }
    
    public void setSex(int sex) {
        //限制属性的范围,不能随便赋值
        if (sex < 0 || sex > 1){
            throw new RuntimeException("性别只能为0和1");
        }
        this.sex = sex;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
  • 使用学生类

    使用学生类时不能直接访问属性必须通过get、set方法

    如果给属性赋值,不符合要求(比如性别就不能设置0和1以外的值),就报异常
    用get方法读取属性,会读取到学生类中转换之后的内容(比如这里的男,女)

    Student student = new Student();
    //student.name = "张三";
    //私有成员变量,不能直接用对象.属性方式访问
    student.setName("张三");
    student.setSex(1);
    student.setAge(11);
    System.out.println(student.getSex());
    
访问修饰符

控制访问权限的关键字称为访问修饰符,有private、default、protected、public

访问修饰符可以用在类,成员变量以及方法前面

局部变量不需要访问修饰符

访问修饰符访问权限大小排序

private < default < protected < public

同类同一个包子类其他类
private(私有的)×××
default(默认的)(不写修饰符)××
protected(受保护的)×
public(公有的)

继承

A类可以通过extends关键字继承B类,继承之后A类可以有有一些B类中的属性或方法,实现代码重复利用

语法:

[修饰符] class 子类 extends 父类{

}

子类也叫派生类,衍生类,subClass

父类也叫基类,超类,superClass

  • 继承的特点

继承只能是单继承,只能有一个父类;一个父类可以有多个子类

继承可以多重继承,A继承B,B继承C

Opject是所有类的父类(所有的类都继承Opject类)

子类可以重写(覆盖)父类的方法

创建子类时,会先执行父类的构造方法

代码案例

父类定义了一个成员变量name,一个方法area( )

子类Retangle继承了父类Shap,Retangle自动有name属性和area( )方法

子类中定义自己的属性,也可以写自己的方法,还以重写父类继承来的方法

  • 父类Shap

    public class Shap {
    
        public String name;
    
        public void area (){
            System.out.println("显示图形的面积");
        }
    }
    
  • 子类Retangle

    public class Retangle extends Shap{
    
        private float width;//矩形的宽度
        private float hight;//矩形的高度
    
        public Retangle() {
            this.name = "矩形";
        }
    
        //构造方法
        public Retangle(float width, float hight) {
    
            this();//调用无参的构造方法,在构造方法中调用其他构造方法,要写在第一行
            this.width = width;
            this.hight = hight;
        }
    
        @Override  //重写,覆盖父类的方法
        public void area() {
            float area = width * hight;
            System.out.println(area);
        }
    }
    
测试代码
public class RetangleTest {
    public static void main(String[] args) {
        Retangle retangle = new Retangle(5,3);
        retangle.area();
        System.out.println(retangle.name);
    }
}
重写override(覆盖)

子类继承父类时,子类对父类的方法代码重新写过,就叫重写

重写的特性:

  • 方法名、参数列表(个数、类型、顺序)、返回值必须一致
  • 访问的权限(修饰符)不能比父类更小(跟父类的访问权限一致或比父类大)
    • 比如 父类的修饰符是 protected 子类的修饰符不能是 private
  • 如果要抛出异常,不能比父类的异常更大
public void test(String str,int i)
    
    
public void test(String a,int d)
重载overload

在一个类中(不一定要继承),如果有多个方法的方法名相同,参数列表不同(个数、类型、顺序),这些同名的方法就称为重载

重载的特性:

  • 方法名相同
  • 参数列表不同(个数、类型、顺序)
public class Rect {
    /**
     * 计算正方形的面积
     */
    public void area(int width){
        System.out.println(width * width);
    }

    /**
     * 计算长方形的面积
     * @param widht
     * @param hight
     */
    public void area(int widht ,int hight){
        System.out.println(widht * hight);
    }

}
构造方法的特点
  1. 构造方法没有返回值,而不是返回值是void

  2. 构造方法的方法名和类名是一致的

  3. 构造方法的目的就是实例化对象(将类进行实例化,创建存放对象的空间)

  4. 构造方法可以通过new进行调用

  5. 一个类里面存在默认的构造方法(无参数),当这个类里面存在他的重构方法,那么默认的无参构造就会消失

相关面试题
  • 构造方法被调用的时候一定会创建对象?

    错误。子类的构造方法执行时,要先调用父类的构造方法,这时候父类并没有创建出对象

  • 重写和重载的区别?

  • 构造方法能重载吗?能重写吗?

    可以重载(一个类可以有多个不同参数的构造方法)

    不可以重写

this和super关键字

这两个关键字都可以指代对象或者方法

  • 当对象用

    public Shap() {
        //this用在构造方法中,代表当前对象
        this.name = "形状";
        System.out.println(this.name);
    }
    
    public void setAge(int age) {
        //this用在用在set方法中,代表当前对象
        //为了区分成员变量和局部变量,因为两个都叫age
        this.age = age;
    }
    
    public void parentArea(){
           super.area();
    }
    
  • 当成构造方法使用

    • 构造方法中调用构造方法,用this代替构造方法名
    • 构造方法中调用构造方法,调用语句只能放在第一行
    • 子类要调用父类的构造方法,用super()
    • 如果子类的构造方法没有调用父类的构造方法,默认调用父类无参的构造方法
    • 如果父类没有无参的构造方法,在子类的构造方法中必须要调用父类有参的构造方法

Parent.java

public class Parent {
    private int age;
    private String name;
    private int sex;

    public Parent(){
        System.out.println("无参");
    }

    public Parent(int age, String name) {
        this();
        this.age = age;
        this.name = name;
        System.out.println("两个参数");
    }

    public Parent(int age, String name, int sex) {
        this(sex, name);
        this.sex = sex;
        System.out.println("三个参数");
    }

    public static void main(String[] args) {
        Parent parent = new Parent(22,"张三",1);
    }
}

Son.java

public class Son extends Parent{

    private int age;
    private String name;
    private int sex;

    public Son() {
        super();//执行父类的构造方法,不写也会自动调用
        System.out.println("son 无参");
    }

    public Son(String name, int sex) {
        this.name = name;
        this.sex = sex;
        System.out.println("两个参数");
    }

    public Son(int age, String name, int sex) {
        this.age = age;
        this.name = name;
        this.sex = sex;
        System.out.println("三个参数");
    }


    public static void main(String[] args) {
        Son son = new Son();
        new Son(22,"赵四",0);

    }
}

多态

一个类在编译时和运行时同一个方法呈现出不同状态

比如:动物有一个发出叫声的方法,他的子类有猫类,猫的叫声为喵喵喵;还有一个子类是狗,狗的叫声是汪汪汪

现在有有一个动物类的对象,调用发出叫声的方法,有可能是:喵喵喵,也有可能是:汪汪汪

形成多态的条件 :

  1. 有继承关系,子类重写父类的方法
  2. 父类类型定义的变量,用子类的实例给他赋值

多态的用处:

​ 统一管理,无限适配或扩展

例如:Windows操作系统中有打印功能,规定好方法,不同类型的打印机(针式、喷墨、激光、彩色、黑白)只要继承和适配答应方法,就可以实现自动打印适配所有的打印机

Animal.java

public class Animal {

    public void shout(){
        System.out.println("动物在叫");
    }
}

Cat.java

public class Cat extends Animal{

    @Override
    public void shout() {
        System.out.println("喵喵喵");
    }
}

Dog.java

public class Dog extends Animal{

    @Override
    public void shout() {
        System.out.println("汪汪汪");
    }
}

测试代码

public class AnimalTest {
    public static void main(String[] args) {
        Animal animal1 = new Animal();
        animal1.shout();

        Cat cat = new Cat();
        cat.shout();

        Dog dog = new Dog();
        dog.shout();

        System.out.println("=====Animal animalCat = cat=======");
        Animal animalCat = cat;
        animalCat.shout();

        System.out.println("=====Animal animalDog = dog=======");
        Animal animalDog = dog;
        animalDog.shout();

    }
}

向上造型 (安全的)

父类 变量 = new 子类( )

父类定义的变量,用子类的实例对象赋值

**注意:**向上造型时,不能调用子类自己定义的方法

    System.out.println("=====Animal animalCat = cat=======");
    Animal animalCat = cat;
    animalCat.shout();

    System.out.println("=====Animal animalDog = dog=======");
    Animal animalDog = dog;
    animalDog.shout();

向下造型 (有条件的)

子类 变量 = (子类) 父类的对象

用父类的对象给子类变量赋值,向下造型必须使用强制类型转换

向下造型分以下几种情况

  1. 直接new一个父类对象赋给子类变量,不允许,运行时会抛异异常
  2. 父类对象是通过子类对象向上造型上去的实例,这种对象可以向下造型,也要强制转换,子类的所有方法都可以使用
  3. 跟2一样的做法,但是换了子类,如猫的子类对象,向下造型成狗,不允许,运行时会抛异常
 //向下造型
 //1.直接用父类创建的对象赋给子类变量,会抛异常
// Cat cat = (Cat) new Animal();

 //把通过向上造型得到的父类对象赋给子类对象,可以调用继承至父类的方法,也可以子类自己的方法
 Animal animal1 = new Cat();
 System.out.println("=====向下造型=======");
 Cat cat1 = (Cat) animal1;
 cat1.shout();
 cat1.eat();

 System.out.println("=====向下造型换了子类的对象=====");
 Animal animal2 = new Dog();
 Cat cat2=(Cat)animal2;//会抛出异常
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值