java编程基础(二)----面向对象

一、面向对象概念

其本质是以建立模型体现出来的抽象思维过程和面向对象的方法(百度百科)
是一种编程思维,也是一种思考问题的方式

如何建立面向对象的思维呢?
1、先整体,再局部
2、先抽象,再具体
3、能做什么,再怎么做

二、类与对象

类:类是一种分类,一个类别,一个模板,它描述一类对象的行为和状态,是一组具有相同特性(属性)与行为(方法)的事物集合
对象:是一个个性的产物,是一个个体的特征,是类的一个实例,有状态和行为。

2.1类对象定义的格式

类的定义:

class 类名称{

     属性类型  属性名称;

     返回类型  方法名称(){

}

     public 类名称(){    //constructor(构造函数)

}

}

注意:构造函数没有返回类型,且名称必须与类名一样;一个java文件可以有很多个class,但是只能有一个public class且名称与文件名称一样(大小写完全一致)。

对象的定义:

一个类要想真正的进行操作,则必须依靠对象,对象的定义格式如下:
类名称 对象名称 = new 类名称() ;

如果要想访问类中的属性或方法(方法的定义),则可以依靠以下的语法形式:
访问类中的属性:对象.属性 ;
调用类中的方法:对象.方法();

例如:

实例化对象:horse= new Horse() ;// 表示实例化了对象,可以使用

horse.eat(); //通过对象调用方法

代码:

public class Horse {
    int high=210;
    int weigh=100;
    void eat() {
        System.out.println("我可以吃草");
    }
    public Horse() {   //构造函数
        
    }
    public static void main(String[] args) {
        Horse horse=new Horse(); //实例化了一个叫horse的对象
        System.out.println(horse.high);  //horse 具有的高度210
        System.out.println(horse.weigh); //horse 具有的重量100
        horse.eat();  //horse的行为可以吃草

    }

}

 

三、面向对象的基本特性

3.1封装

封装性就是尽可能的隐藏对象内部细节,对外形成一道边界,只保留有限的接口和方法与外界进行交互。封装的原则是使对象以外的部分不能随意的访问和操作对象的内部属性,从而避免了外界对对象内部属性的破坏。

  可以通过对类的成员设置一定的访问权限,实现类中成员的信息隐藏。

  • private:类中限定为private的成员,只能被这个类本身访问。如果一个类的构造方法声明为private,则其它类不能生成该类的一个实例。
  • default:类中不加任何访问权限限定的成员属于缺省的(default)访问状态,可以被这个类本身和同一个包中的类所访问。
  • protected:类中限定为protected的成员,可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的所有其他的类访问。
  • public:类中限定为public的成员,可以被所有的类访问。

封装原则:

• 将不需要对外提供的内容都隐藏起来。

• 把属性都隐藏,提供公共方法对其访问。

Java中可以通过对类的成员设置一定的访问权限,实现类中成员的信息隐藏。

 如下面的这个student类,就是使用了封装,将类中的属性name 、age和score私有化,使外部不能直接访问他们,只能通过public类型的对他们方法进行操作。

class Student {
    private String name;//声明属性 ,并设为私有类型,起到封装的作用
    private int sex;

    public String getName() { //设置getter方法,因为变量设为了私有,对象无法访问类中的属性,需要用getter方法获取变量
        return name;
    }

    public void setName(String name) { //设置setter方法,因为变量设为了私有,对象无法访问类中的属性,需要用setter方法给变量赋值
        this.name = name;
    }

    public int getSex() {
        return sex;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

java中这样做的原因:

  • 将数据与行为分离,也就是java的面向对象的概念。   

  对象就是属性+行为,封装就是把对象的私有属性封装起来,只有通过自己公开的行为去改变(获得)对象内部的私有属性信息,而那些public的方法正是面向其他对象的接口,只有通过接口去改变(获得)对象的私有属性。

  • 安全性

  设想,上面的student类的sex字段表示性别,理论上,sex只接受两个值, '0 '和 '1 ',但如果你把sex字段设为public,你很难限制你的用户只给它赋 '0 '或 '1 '值。将sex设为private,再用setSex()来设置性别,你就完全可以控制这种行为了。而且你还可以控制只能get不能set,或相反,但如果是public就不行了。别外有一点属性我们可能并不希望其他用户对我们的属性进行写操作,这个时候,可以直接不写setX方法。这就是只读属性了。

3.2继承

继承的格式:

class 子类名 extend 父类名

父类(也称基类),子类(也称导出类)。如果两个类存在继承关系,则子类会自动继承父类的方法和变量,在子类中可以调用父类的方法和变量。

在java中,只允许单继承,也就是说 一个类最多只能显示地继承于一个父类。但是一个类却可以被多个类继承,也就是说一个类可以拥有多个子类。

1.子类继承父类的成员变量

  当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。具体的原则如下:

  1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量;

  2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。

2.子类继承父类的方法

  同样地,子类也并不是完全继承父类的所有方法。

  1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;

  2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为重写(overrite),即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。

注意:隐藏和覆盖是不同的,隐藏是针对成员变量和静态方法,覆盖是针对普通方法

3.构造函数

       子类是不能够继承父类的构造器,但是要注意的是,如果父类的构造器都是带有参数的,则必须在子类的构造器中显示地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super关键字调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。

 用代码来举例:

先写一个Animal的父类,其构造函数是无参的,Dog继承Animal,并且重写了eat方法;

public class Animal {
    private int age;
    public Animal() {
        System.out.println("Animal constructor");
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age=age;
    }
    public void eat() {
        System.out.println("eat food");
    }
    
}
public class Dog extends Animal {
    private String color;
    public Dog(String color) {
        this.color=color;
    }
    public void run() {
        System.out.println("Dog can run.");
    }
    
    public void fatherEat() {
        super.eat();
    }

    @Override
    public void eat() {
        System.out.println("dog eat bone");
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Dog dog=new Dog("red");
        dog.eat();
        dog.fatherEat();

    }

}

Animal constructor
Dog constructor
dog eat bone
eat food


可以看出,因为Animal构造器是无参的,所以在子类Dog写构造器时并没有super关键字,系统会自动调用父类Animal 的构造器!

注意:父类的构造器调用以及初始化过程一定在子类的前面。

3.3多态

重载(Overloading)

  • 方法重载是让类以统一的方式处理不同数据类型的手段。
  • 一个类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法。
  • 返回值类型可以相同也可以不相同,无法以返回型别作为重载函数的区分标准。

重写(Overriding)

  • 子类对父类的方法进行重新编写。如果在子类中的方法与其父类有相同的的方法名、返回类型和参数表,我们说该方法被重写 (Overriding)。
  • 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
  • 子类函数的访问修饰权限不能低于父类的。

对于重载;主要是针对一个类中具有相同名字不同参数的方法。当调用方法是,编译器会根据传递的参数自动判定调用具体的方法;

对于重写:主要是针对子类对父类的方法进行重写,必须与其父类具有相同的方法名、返回类型和参数表,上面代码中Dog类eat函数就对Animal类的eat方法进行重写。

向上造型

定义:子类引用的对象转换为父类类型称为向上转型。

我们根据之前定义的Animal 父类和 Dog子类可以实现。

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Animal animal=new Dog("RED");  //向上造型,将一个Dog的子类对象转化成Animal的父类类型。
        animal.eat();     //这里animal调用的方法仍是子类方法

    }
输出
Animal constructor
Dog constructor
dog eat bone

 

注意:向上转型时,子类单独定义的方法会丢失。比如上面Dog类中定义的run方法,当animal引用指向Dog类实例时是访问不到run方法的,animal.run()会报错。

向下造型

一般来说不怎么用向下造型(坑比较多),这里不详细介绍,但是列出向下造型时的注意事项;

  • 向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型
  • 向下转型只能转型为本类对象(猫是不能变成狗的)。

 

 

 

 

 

posted @ 2020-05-10 15:29  Yunus  阅读(203)  评论(0编辑  收藏  举报