Java 面向对象及其三大特性

Java 面向对象及其三大特性

这是 Java 基础增强系列第一篇文章,主要讲述面向对象及其三大特性

面向对象

1.1 为什么会出现面向对象这种技术?

要回答这个问题,可就说来话长了。很久以前,软件开发领域还是一片混沌,开发软件一直面临着复杂性的难题,到处使用 goto 语句,程序随意跳转。

之后,有大神提出「结构化编程」,它将程序的控制流程规定为顺序、循环、选择,而程序共通的部分归结为函数。这极大的降低了软件开发的复杂性,使得软件领域进一步发展。但是,这种方法虽降低了控制流程方面的难度,但在复杂数据的处理上仍然很无力。

再后来,当然就是又有大神提出「面向对象」的设计方法啦,它把数据和处理方法结合起来,这便是对象一词的由来,面向对象编程也由此得名。然后,从抽象的角度来考虑,就把相同的部分提取出来,称之为类。慢慢的,完善了很多面向对象的具体的细节内容,后续博文会接着介绍。

其实,说穿了,面向对象技术就是为了降低软件开发的复杂性,让跟更多的像我这样的傻帽也能来 coding ,感谢这些大神。

1.2 面向对象技术是个什么样的东西?

目前还没有想到该怎么样回答这个问题,通常俗气的回答是扯一下它的优点,还有三大特性。这里就先空着吧。

1.3 面向对象的作用?

面向对象的由来,已经讲过它就是为了简化软件开发的难度而出现的一门技术。最大的作用自然就是这个啦。

再讲细一点就是能够将问题进行归类和抽象。将属性和功能归结为类,将复杂的问题分成各个模块,降低开发的复杂性。

封装

2.1 什么是封装?

面向对象中,将数据(字段)和处理数据的操作(方法)封装在一个不可分割的实体(类)中,只保留一些接口(非 private 类型的方法)来接收外界输入的数据或者向外界输出数据。

2.2 为什么要进行封装?

  • 向外界隐藏信息

有时候,类的一些属性想要保持私有,不希望外界访问,可以这样做:

public class girl{
    //这里只提供外界访问 girl 姓名的方法,而不提供访问年龄的方法,就是一种数据隐藏。
    private int age;
    private String name;

    public String getName(){
        return this.name;
    }
}
  • 可以灵活修改类的内部实现

有时候,项目开开发中,临时决定要对类进行修改,却又不能影响其他已经使用到这部分内容的程序。例如,将 int 类型的年龄改为 String 类型

//修改前
private int age;
public void setAge(int age){
        this.age = age;
}
//修改后
private String age;
public void setAge(int age){
    this.age = String.valueOf(age);
}//这样修改内部实现,使得外部代码仍然有效,不需改变
  • 对类的成员进行精准控制

有时,需要对字段添加一下必要的控制信息。例如,设定用户年龄时不得设置大于 150

public void setAge(int age){
    if(age > 150){
        //提示用户年龄不得设置大于 150 
    }
    this.age = age;
}

继承

3.1 为什么会出现继承这种技术?

使用面向对象的思想编程时,会编写很多类,而这些类之间就不可避免的有相同的属性和方法。使用继承可以极大的复用代码,非常有效。

3.2 继承是什么?

利用已存在的类作为父类,新编写的类作为子类,子类就可以 复用父类的代码。

3.3 继承有哪些语法?

所谓语法,其实就是编程语言规定的一系列规则。只有遵循这种规则,才能够通过编译器的检查,编译成为 .class 文件,最终才能有 Java 虚拟机按照程序员的意图去执行程序。

  • 子类仅仅拥有父类的非 private 属性成员方法
  • 子类可以拥有自己的成员和方法,对父类进行扩展
  • 子类可以重写父类的方法

构造器:

对于父类的构造器,子类也同样不能够继承,但是能够在子类的构造函数中利用 super 关键字调用

public class People{//父类
    private int sex;
    private String name;
    public People(String name,int sex){
        this.name = name;
        this.sex = sex;
    }
}

public class Girl extends People{//子类
    private int age;
    public Girl(String name,int sex,int age){
        super(name,sex);
        //若需要调用父类的构造函数,则 super 关键字必须在子类构造函数中的第一行出现
        this.age = age;
    }
} 

protected 关键字:

有时,父类的某些属性只希望子类能够访问,而不允许外界能够访问。就可以采用protected 关键字来做修饰符

public class People{
    protected int getMoney(){//这样就能保证该方法只有其子类能够访问,外界不可访问
        return this.money;
    }
}

向上转型:

由于继承使得子类拥有了父类的属性,就会有这样的情况: Girl 可以说自己是 People (向上转型),但是 People 不能说自己是 Girl (向下转型)。

public void f(People p){
    System.out.println(p.getName());
}

@Test
public void test(){
    Girl g = new Girl();
    f(g);//这样是可以的,这里可以直接向上转型,不会出错
}

public void f1(Girl g){
    System.out.println(g.getName());
}

@Test
public void test1(){
    //但是,要实现向下转型,必须先向上转型后,才可以向下转型。直接向下转型通常不可以,是因为子类通常都做了修改,所以父类并不能拥有子类的属性,代表不了子类。
    People p = new Girl();//向上转型了
    f1(p);//向下转型
}

总结:学习语法时,一定不可以钻进语法的牢笼里出不来,否则永远也学不明白。应该把重点放在为什么会有这种语法出现上面?

比如,因为想要复用代码,所以出现了继承;因为有继承就引出了父类的构造函数、私有属性是否能够被子类继承;引出了怎样能够仅仅让子类访问父类的属性;引出了向上、向下转型的概念。

多态

4.1 为什么会有多态这种技术出现?

在实际的软件开发当中,需求总是会不断改变的,这可不是能够避免的。一旦需求改变,那我们之前写的代码可能要大改,甚至是重写。这可怎么办?

通过各种手段提高代码的通用性,可扩展性,就可以很好的解决这个问题,多态就是其中之一。

4.2 什么是多态?

通常的解释是:同一个处理手段能够带来不同的处理结果。其实,这句话忘记了一个前提,这是针对用户而言,是这样一种牛逼的存在。

对于设计者而言,这可是我花了时间精心设计的结果啊,针对每一种情况都做出了相应的处理。不然,你以为世界上还真有这么牛逼的存在?

多态其实分为两种多态,一种是函数重载,严格意义上算不上是多态。另一种是面向对象独有的多态,构成多态的条件后,在程序运行时期判断父类引用指向的对象的类型后,再选择调用哪个对象的方法。

4.3 多态怎么实现呢?

构成多态的条件就是:父类引用指向子类对象,子类重写了父类的方法

上面说了这么多,多态该怎么实现呢?这里以小柯买汽车为例,写一个程序


 abstract class Car{//抽象的汽车类
    public void run();
}

 class BMW extends Car{//宝马汽车类
    public void run(){
        System.out.println("BMW...");
    }
}

 class Benz extends Car{//奔驰汽车类
    public void run(){
        System.out.println("Benz...");
    }
}

 class People{//定义一个 People 类
    private String name;
    private Car car
    public People(String name,Car car){
    //这里 Car 采用参数多态,任何类型的汽车都可以作为参数,非常重要
        this.name = name;
        this.car = car;
    }
    public void driveCar(){
        this.car.run();
    }
}

@Test
public void test(){
    //小柯买了一辆 BMW ,在路上开
    People p = new People("xiaoke",new BMW());
    p.driveCar();//此处开的是 BMW 的 run() 方法

    //小柯买了一辆 Benz ,在路上开
    People p = new People("xiaoke",new Benz());
    p.driveCar();//此处开的是 Benz 的 run() 方法
    /*
        这个例子就很明显的让用户在进行相同操作( driveCar() )时,得到了不同的结果。
    */
}

这里再举一个返回类型采用多态的例子,

class CarFactory{
    public  static Car newCar(String car){
        if(car.equals("BMW")){
            return new BMW();
        }
        if(car.equals("Benz")){
            return new Benz();
        }   
        if(car.equals("BYD")){
            return new BYD();
        }
    }
}

@Test
public void test(){
    Car c1 = CarFactory.newCar("BMW");
    Car c2 = CarFactory.newCar("Benz");
    Car c3 = CarFactory.newCar("BYD");
    //这里就实现了返回类型的多态
}

说穿了,多态就是精心设计的一种手段,对于用户来说,同一种操作可以得到不同的处理结果。

对设计者来说就是为了程序有更好的可扩展性,更灵活。至于设计者怎么实现多态,这就是编程语言定义的语法规则了,上述例子已经完整的展现了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值