面向对象基础篇---类与对象---如何编写一个标准的JAVA类

什么是面向对象

(object - oriented - programming ,OOP )面向对象程序设计

  • 一切事物皆对象,在面向对象编程的过程中,我们可以把所有的事物抽象成一个个对象,根据人的认知,将他们分成一个个的类,通过继承,组合等等将所有的事物描述出来,在编程过程中,只需要对这个对象发送指令,对象自己就会完成指令所描述的行为

    例如

    calss Dog{
    //添加属性
    int age ;
    String name ;
    char gender ;
    //添加方法
    public void fly(){
      //....
    }
    }
    //在我们创建一只特定的狗之后,我想让他飞 
    //这时只需 发送指令给这个狗(调用这个狗的行为方法)
    Dog dog = new Dog();
    dog.fly();//直接起飞
    
  • 通俗的说,我们可以把面向对象过程中人扮演的角色看作,指挥者

    我们只需发送指令,让特定的人来完成指令内容

    这个过程,省时省力并且结果比较理想

什么是面向过程

Procedure Oriented 面向过程

  • 面向过程的基本流程

    分析问题 ====》 分解问题 ====》 解决问题

    在这个当中所有的问题都需要人来亲力亲为的解决

    比如“做饭”

    首先,确定吃什么,其次去购买材料,之后再做饭,再之后才能吃

    而面向对象,以吃饭为例,类似于点外卖,我们们只需告诉商家,我们要吃什么,商家就会帮我做好。

  • 在面向过程的编程中,人可以看作是 执行者,每个过程都要亲力亲为

    费时费力,且结果不一定理想

处理一件事情,能不能完全面向对象

很显然,不可能完全面向对象

就例如点外卖,虽然点的人没有做饭,但商家是不是还要执行这个做饭过程,

所以处理一件事情最少需要一个执行者

  • 因此面向对象和面向过程并不是互斥的,面向对象基于面向过程

类与对象

(calss) 类 ,(object) 对象

  • 我们可以将类想象成一个摸具,将对象想象成模型。 由类构造对象的过程称之为类的实例

  • 但凡存在于现实世界中的所有事物,都可以称之为对象

  • 我们将具有相同属性,相同行为的对象进行统称和分类

例如,拉布拉多,和雪纳瑞,都可以称之为一个对象,他们可以分到Dog类中

  • 我们来思考一个问题,先有类,还是先有对象?

    现实生活中

    人是通过观察已有的事物,并对其进行分类。故先有对象后又类

    但在编程中

    则是先有类,后有对象

    因此,我们在编程中,一般情况下都是先创建类,再实例化对象

创建类&&创建对象

创建一个类
  • 语法

    /*
    权限修饰符 类型 class 类名
         构造代码块
            静态代码块
            成员变量/实例变量
            静态变量
            构造函数/构造器
            成员函数/实例函数
            静态函数
            继承而来的函数
            修改器
            访问器
    }
    */
    // 例如
    public class Dog{
        String name ;
        int age ; 
        char gender ;
        
    }
    //需要注意的是,在一个文件中最多有一个public 修饰的类
    //当有public修饰的类时,类名必须与文件名一致
    
创建一个对象
语法
/*
类名 对象名 = new 类名()   // 准确来说应该是 = new 构造方法;
*/
// 例如,以上方的Dog类为例
Dog  dog = new Dog();

属性/方法
  • 访问属性或方法
//我们可以通过 对象名.属性/方法
//例如 ,打印dog的属性
System.out.println(dog.name);
System.out.println(dog.age);
System.out.println(dog.gender);
/*
执行输出:
null
0
   (char类型是一个空字符)
*/

/*
可以看到,即使我们并没有赋予属性一个准确的值
系统也会给变量生成一个默认值
这个过程称之为隐性赋值;

当然,我们在编写类的过程中就可以直接对属性赋予初值

例如:

public class Dog{
    int age = 1 ;
    String name = "小花";
    char gender = '公' ;    
}

这种直观的可以看到的赋值

我们称之为 显性赋值

并且对于拥有显性赋值的属性

在创建对象时,并不是直接将值赋给了属性

而是先对属性隐性赋值,再进行显性赋值

  • 修改属性
//修改属性值 可以通过 对象名.属性= ;
//例如:
dog.name = "黑豹”;
dog.age = 2;
dog.gender = '公' ;
//此时我们再打印
System.out.println(dog.name);
System.out.println(dog.age);
System.out.println(dog.gender);
/*
执行输出:
黑豹
2
公
*/

看起来是不是很简单,很方便?

但是这样简单的访问又存在很大的漏洞与缺陷

属性可以随意修改,访问。

就比如 :

一只狗的年龄

我通过 dog.age = -1 ; 使这只狗的年龄变为-1岁,

这可能吗?什么事物的年龄可以是负数?
显然,这在常识上是不合理的,具有很大的业务逻辑错误

那具体要怎么解决呢? 接着往下看

封装

如何解决属性的安全性,避免一些业务逻辑上的错误

在这里就不得不谈谈封装了

  • 两层含义:
    • 将独立单元或者多个数据进行整体的封装,目的在于重复利用和操作,不需要过多在乎封装的内容,我们只需要调用即可,底层对于调用者而言是透明的
    • 使用权限修饰符private来修饰属性,将属性私有化,保证数据的安全性

写到这里又产生了问题,我们将属性私有化之后,外部将无法访问,那如何进行相关属性的赋值呢?

访问器

顾名思义, 就是一个让外界通过其访问类的内部属性的方法

    • 语法:

      public 属性类型 方法名(){

      ​ return 属性名 ;

      }

      一般我们将方法名命名为 get属性

public class Dog{
    private String name ;
    private int age ;
    private char gender ;
    //属性全部私有化
    
    //通过一个公开的方法,让外界获取属性
    public String getName(){
        return name ;
    }
    public int getAge (){
        return age ;
    }
    public char getGender(){
        return gender ;
    }
}
// 拥有访问器之后,我们就可以通过 对象名.访问方法,来获取属性的值
Dog dog = new Dog();
System.out.println(dog.getName());
System.out.println(dog.getAge());
System,out.println(dog.getGender());
/*
执行且成功访问到属性
*/

解决类访问问题,那属性赋值怎么办呢? 同理,创建公开的修改方法

修改器

顾名思义, 就是一个让外界通过其改变内部属性的方法

    • 语法

      public void 方法名(变量类型 变量名){

      ​ this.属性 = 变量名 ;

      }

      一般我们将方法名命名为 set属性

public class Dog{
    private String name ;
    private int age ;
    private char gender ;
    //属性全部私有化
    
    //通过一个公开的方法,让外界获取属性
    //访问器
    public String getName(){
        return name ;
    }
    public int getAge (){
        return age ;
    }
    public char getGender(){
        return gender ;
    }
    
    //通过一个公开的修改方法,让外界修改属性
    //修改器
    public void setAge(int age) {
        /*
        修改器的好处在于我们可以判断传进的变量是否符合逻辑
        并自己决定是否修改属性值
        */
        if(age<0||age>30){
            this.age = 0;
            //加上判断如果狗的年龄不在这个范围则赋默认值
        }
        this.age = age;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public void setName(String name) {
        this.name = name;
    }
}
// 拥有修改器之后,我们就可以通过 对象名.修改方法,来修改属性的值
Dog dog = new Dog();
dog.setName ("小黄");
dog.setGender('公');
dog.setAge(2);
System.out.println(dog.getName());
System.out.println(dog.getAge());
System,out.println(dog.getGender());
/*
执行输出
小黄
公
2
*/
//已成功修改
this 指针
  • this指针指向当前对象的属性

可以看到,在修改器中使用到了 this.属性名。

//修改器  
public void setGender(char gender) {
        this.gender = gender;
    }

这是因为修改器方法参数与属性名相同

而java变量查找符合就近原则

先在函数内部搜索变量,再到函数外部搜索

倘若写成下面这样,那两个gender都是传入参数

 public void setGender(char gender) {    
     gender = gender;  
 }

当然你也可以使用别的变量名来定义传入参数,但不建议这么写,因为规范!!!

到这里其实我们已经基本掌握了创建一个类,并实例化一个对象的方法

但是,仔细想想创建一个对象并初始化属性,几个属性我就要写几行代码

倘若我要创建好几个对象呢,这是就会发现这样写其实非常臃肿

Dog dog = new Dog();
dog.setName ("小黄");
dog.setGender('公');
dog.setAge(2);
System.out.println(dog.getName());
System.out.println(dog.getAge());
System,out.println(dog.getGender());

那有没有办法解决呢?

构造函数
  • 语法:
修饰符 类名称(){
    
}

前面说到 创建一个对象的语法为:

类名 对象名 = new 类名()

准确来说应该是 = new 构造方法;

构造函数是一个函数名与类名一致的方法。

可是我明明没有写这个所谓的构造方法啊

这是因为:

在java类中,如果没有自己定义的构造函数时,JVM会自动生成一个无参的构造函数,方便我们构建一个属性都是默认值的对象

但是当我们定义了一个构造函数时,JVM价格不在自动生成这个无参的函数,如果需要这个无参的构造函数,需要自己定义,建议一定要写无参方法,因为规范!!!

public class Dog {
    private String name ;
    private int age ;
    private char gender ;
    //有参构造方法
    public Dog(String name, int age, char gender) {
        this.age=(age<0||age>30)?0:age;
        this.name = name;
        this.gender = gender;
    }
    //无参构造方法
    public Dog(){
        
    }
    public void setAge(int age) {
        this.age=(age<0||age>30)?0:age;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public char getGender() {
        return gender;
    }
}
//这时当我们创建对象时只需要调用有参的构造方法即可
Dog dog1 = new Dog("小黄",2,'公');
Dog dog1 = new Dog("小黑",6,'母');
//通过访问器输出发现,已经成功在擦汗黄建对象的同时,对其属性进行了初始化

一个标准的java类

1、所有的成员变量都要使用private关键字修饰
2、为每一个成员变量编写一对儿Getter/Setter方法
3、编写一个无参数的构造方法
4、编写一个全参数的构造方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值