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

一、封装

封装是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。在java中我们一般使用private对类中属性或方法进行封装。

使用封装能够更好的保护代码,防止有的代码被其他类的代码随意访问,加强了代码的安全性;而且适当的封装能使代码更容易理解和维护。

我们可以这样实现封装:

class Packging{
    private String secret="secret";
    public String addressable="addressable";
    private void fun(){
        System.out.println("封装的");
    }
    public void pfun(){
        System.out.println("公开的");
    }
}

这样secret属性和fun方法就只能在Packging类中能访问到,在其他类中访问不到,这就实现了封装。

1.2、getter和setter

被private修饰的属性其他类中不能调用,但是可以使用getter和setter方法进行访问及修改。

getter方法可以对被private修饰的方法进行访问。
setter方法可以对被private修饰的方法进行修改。
我们以上面被封装的secret为例,介绍如何使用这两个方法

public class Test {
    public static void main(String[] args) {
        Packging packging=new Packging();
        packging.getSecret();
        packging.setSecret("a");
    }
}
class Packging{
    private String secret="secret";
    public String addressable="addressable";
    private void fun(){
        System.out.println("封装的");
    }
    public void pfun(){
        System.out.println("公开的");
    }

    public String getSecret() {
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }
}

不知道你们会不会有一种想法,既然也可以通过getter和setter访问及修改,那还不如直接将其修改为public,这样还可以减少代码量,但事实不是如此,我认为有以下三个原因会存在这两个方法

  1. 可以在setter方法中编写一些内容,比如使用private修饰用户名,当用户想要修改用户名为傻逼等一系列敏感词,我们就可以在setter中进行拦截,不能让他修改。
  2. 绝大部分的Java框架、类库在使用的时候都是调用set、get方法来设置数据、获取数据。如果我们不遵守这个规则,就无法使用这些东西,那岂不是还得重复造轮子。
  3. 若我们有一个变量时public修饰,此时它已经在很多类中使用,而我们又向修改这个变量,岂不是要进行大量重复操作,既麻烦又容易出错,何不使用封装,直接使用setter方法修改一次即可。

二、继承

继承简单来说就是子类继承了父类的特征和行为。

在这里插入图片描述
图中食草动物和食肉动物就是动物的子类,动物就是食草动物和食肉动物的父类,继承关系应该符合is a ;比如食肉动物is a 动物。
那么java中如何实现继承,需要使用extends 关键字:

extends关键字

比如我们创建一个Animal类,实现一个动物都有的方法eat,在创建Cat类时使用extends继承Animal的eat方法,就不必再写一个eat方法,这样使代码更加简洁。

public class Animal {
    public   void eat(){
        System.out.println("eat");
    }

    public static void main(String[] args) {
        Cat cat=new Cat();
        cat.eat();
    }
}
class Cat extends Animal{

}
//输出结果  :   eat

在java中只能单继承,也就是说Cat类如果继承了Animal类,便不可再继承其他类。继承虽然为设计带来很大的便捷,但是也不能出现多层的继承,一般继承超过三层,那么就需要考虑重构。如何防止出现多层继承?可以使用final关键字,
final关键字修饰类表示该类不能再被继承,比如上面的代码,如果我们使用final关键字修饰Animal类,再使用Cat继承Animal时就会报错。

super关键字

我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类

public class Animal {
    public   void eat(){
        System.out.print("父类");
    }

    public static void main(String[] args) {
        Cat cat=new Cat();
        cat.tyrEat();
    }
}
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.print("子类");
    }
    public void tyrEat(){
        super.eat();
        this.eat();
    }
}
//输出结果:父类子类

在继承中若我们new一个子类对象,会先加载父类,再加载子类,看以下代码:

public class Animal {
    public Animal(){
        System.out.println("父类");
    }
    public  void eat(){
        System.out.println("父类");
    }

    public static void main(String[] args) {
        Cat cat=new Cat();
    }
}
class Cat extends Animal{
   public Cat(){
       System.out.println("子类");
   }
}
//输出结果:父类 子类

三、多态

多态是同一个行为具有多个不同表现形式或形态的能力。
多态存在的三个条件:

  1. 继承
  2. 重写
  3. 父类引用指向子类对象(向上转型)

我们先来看看向上转型

向上转型

1.直接赋值
比如上述代码若有向上转型就可以写为 Animal cat=new Cat();
2.方法传参
假设我们现在还有一个Dog类继承Animal类,编写一个fun方法,调用eat方法,那么我们可能需要这样写

public class Animal {
    public  void eat(){
        System.out.println("eat");
    }
    public static void main(String[] args) {
        Cat cat=new Cat();
        cat.fun(cat);
        Dog dog=new Dog();
        dog.fun(dog);
    }
    public  static void fun(Cat cat){
        cat.eat();
    }
    public  static void fun(Dog dog){
        dog.eat();
    }
}
class Dog extends Animal{
}
class Cat extends Animal{
}

而如果我们使用向上转型,将fun的参数改为父类Animal animal,就不用再写重复代码:

public class Animal {

    public  void eat(){
        System.out.println("父类");
    }
    public static void main(String[] args) {
        Cat cat=new Cat();
        cat.fun(cat);
        Dog dog=new Dog();
        dog.fun(dog);
    }
    public  static void fun(Animal animal){
        animal.eat();
    }
}
class Dog extends Animal{
}
class Cat extends Animal{
}

3.方法返回
这个和第二个类似,若返回值类型都设计为父类,便不用再写重复类型代码。

多态实例

比如我们编写一个方法,还是eat,但是狗喜欢吃火腿肠,猫喜欢吃鱼,我们就可以这样写

public class Animal {
    public  void eat(){
        
    }
}
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("喜欢吃火腿肠");
    }
}
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("喜欢吃鱼");
    }
}

父类方法体中什么都不用写,这样一个引用,表现出多种不同的形态就叫多态。现在是不是对多态更了解了。

多态的好处

  1. 类调用者对类的使用成本进一步降低
  2. 降低代码的圈复杂度
  3. 可扩展能力更强

四、补充知识

向下转型

假设我们设计Bird类继承Animal类,不仅会吃,还会飞,我们这样定义 Animal bird=new Bird();那么此时我们调用bird的飞方法就会报错(因为虽然new的是Bird,但是还是属于Animal类,Animal中没有fly方法,自然会报错)。此时就需要向下转型:

public class Animal {
    public  void eat(){
    }

    public static void main(String[] args) {
        Animal bird=new Bird();
        bird=(Bird)bird;
        //向下转型
        ((Bird) bird).fly();
    }
}
class Bird extends Animal{
    @Override
    public void eat() {
        System.out.println("eat");
    }
    public void fly(){
        System.out.println("fly");
    }
}

但是这样还是不保险,万一我们不知道bird原来是不是Bird类型也会报错(万一它是RedBird呢?),此时我们需要使用instanceof进行判断bird引用是不是Bird类的实例。

public class Animal {
    public  void eat(){
    }

    public static void main(String[] args) {
        Animal bird=new Bird();
        bird=(Bird)bird;
        if(bird instanceof Bird){
            ((Bird) bird).fly();
        }
    }
}
class Bird extends Animal{
    @Override
    public void eat() {
        System.out.println("eat");
    }
    public void fly(){
        System.out.println("fly");
    }
}

这样就保险很多啦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

友农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值