【转】JAVA基础:一个案例搞懂类、对象、重载、封装、继承、多态、覆盖、抽象和接口概念及区别(上篇)

写在前面:

转载自:知乎  飞爱学习  作者:一个敲代码的汽车人

原文链接:https://zhuanlan.zhihu.com/p/139018397

这篇主要讲 重载overload 、封装Encapsulation。也是工程化的设计思想的产物。


1 类(Class)、对象(Object)和构造器(Constructor)

1.1 案例

要求设计一个矩形的面积计算器,输入为矩形的高(height)和宽(width),输出为矩形的面积(area)。

1.2 代码

对JAVA的语法有最基本的了解后可以写出如下代码:

class Rectangle{                                //创建矩形类
    public double height;                       //定义类的成员变量
    public double width;                           
    
    public Rectangle() {                        //定义无参构造器--可省略
    }
    
    public void calcuArea() {                   //定义类的方法--面积计算
        System.out.println("面积为:"+height*width);
    }
}

public class Test{
    public static void main(String[] args) {
        Rectangle rec=new Rectangle();          //创建矩形对象--调用构造器
        rec.height=1;                           //高度赋值
        rec.width=2;                            //宽度赋值
        rec.calcuArea();                        //调用面积计算方法
    }
}

1.3 代码分析

以上代码包含以下概念:
1、类(Class):类是构造对象的模板或蓝图,其由成员变量和方法构成,前者记录数据,后者记录数据的操作过程。
2、对象(Object):对象是类的实例化,一个类可以有多个对象。
3、构造器(Constructor):构造器是一种特殊的方法,用于对象实例化时的初始化操作。

注意:

  • 构造器总是和关键字“new”一起使用。
  • 构造器的方法名必须和类名一致!
  • 任意一个类都包含至少一个构造器,当没有自定义构造器时,编译器会自动设定为无参构造器;但如果自定义了有参构造器,并需要调用无参构造器时,就必须自己手动写。
  • 构造器中,this()用于调用同一类中的其他构造方法;super()用于调用父类的构造方法。都必须位于构造方法中的第一行,且两者不能同时存在。

思考:以上代码虽然实现了基本功能,但其功能不够完善,比如当用户输入的高度和宽度为字符串时,代码就会报错,那怎么才能在不给用户输入添加麻烦的情况下实现功能呢?


2 重载(Overload)

2.1 案例

要求设计一个矩形的面积计算器,输入为矩形的高和宽(数字或者字符串输入,假定用户输入的字符串都是数值型字符串),输出为矩形的面积。

2.2 代码

class Rectangle{                                    
    public double height;                           
    public double width;                           
    
    //定义无参构造器--可省略
    public Rectangle() {                            
    }
    
    //定义有参构造器1
    public Rectangle(double height,double width) { 
        this.height=height;       //this指代当前对象,用于区分方法中的形参
        this.weight=width;
    }
    
    //定义有参构造器2
    public Rectangle(String height,String width) { 
        this.height=Double.valueOf(height);
        this.weight=Double.valueOf(width);
    }
    
    public void calcuArea() {                   
        System.out.println("面积为:"+height*width);
    }
}

public class Test{
    public static void main(String[] args) {
        Rectangle rec=new Rectangle(1,2);       //创建矩形对象--调用构造器1
        rec.calcuArea();                        //调用面积计算方法
        
        Rectangle rec1=new Rectangle("1","2");  //创建矩形对象--调用构造器2
        rec1.calcuArea();                       //调用面积计算方法
    }
}

2.3 代码分析

以上代码包含以下概念:
重载(Overload):指类中多个方法具有相同的名字,但参数类型或返回类型不同的现象。重载的设定是为了方便用户操作,以相同的方法名实现特定的功能,同时匹配不同的参数类型以满足功能的扩展性和需求的多样性。在上面的代码中我们实现了构造器方法的重载,完美解决了用户输入多样性的问题,但重载并不局限于构造器方法,它可以适用于类中的任何方法。

注意:

  • 不允许方法名和参数类型相同,但返回类型不同的情况出现,因为程序无法判断返回哪一个。
  • 方法的形参类型相同但顺序不同也构成重载,如add(double a,int b)和add(int a,double b)。

思考:以上代码虽然解决了之前提出的问题,但是仍存在一个巨大的安全隐患,即用户可以直接通过“rec.height”和“rec.width”对矩形的高和宽赋值,这会导致两个我们不愿意看到的情景。一是,当用户输入非常规数值(比如-1)时,计算的结果是没有意义的;二是,后期更改程序时难以维护,比如我们后期要将height的变量类型改为String类型,那么就必须更改每一处height赋值的地方(如代码1.2)。那么,如何改进呢?


3 封装(Encapsulation)

3.1 案例

要求设计一个矩形的面积计算器,输入为矩形的高和宽(数值输入),且数值都应大于零,输出为矩形的面积。同时要避免2.3中所述的问题。

3.2 代码

class Rectangle{
    private double height;                          //私有化实例字段
    private double width;
    
    public void setHeight(double height) {          //定义更改器方法
        if (height<0) {
            this.height =0;
        }
        else {
            this.height = height;
        }
    }
    public void setWidth(double width) {
        if (width<0) {
            this.width =0;
        }
        else {
            this.width = width;
        }
    }
    public double getHeight() {                     //定义访问器方法
        return height;
    }
    public double getWidth() {
        return width;
    }
    public void calcuArea() {
        System.out.println("面积为:"+height*width);
    }
}

public class Test{
    public static void main(String[] args) {
        Rectangle rec=new Rectangle();
        rec.setHeight(-1);                         //设定高
        rec.setWidth(2);                           //设定宽
        rec.calcuArea();   
        //读取高和宽
        System.out.println("高为:"+rec.getHeight()+" 宽为:"+rec.getWidth());
    }
}

3.3 代码分析

以上代码包含以下概念:
封装(Encapsulation):通过私有化类的成员变量,并创建相应的公有化的更改器(即设定成员变量的独立方法,如setHeight)和访问器(即读取成员变量的独立方法,如getHeight)实现对成员变量的封装。

设计用意:

  • 成员变量私有化的设计,使用户无法通过“rec.height”和“rec.width”对矩形的高和宽赋值与读取。
  • 更改器和访问器公有化的设计,使用户可以随意调用,实现对成员变量的赋值与读取。
  • 在更改器中我们可以设定数值规范,避免因用户的错误输入所带来的问题。
  • 在后期调试中,我们只需要改写类的成员变量类型及相应的更改器便可,无需修改每个实例化对象的相关代码。

4 参考文献

[1]《Head First Java(第二版·中文版)》

[2]《Java核心技术·卷 I(原书第11版)》

[3] 菜鸟教程:https://www.runoob.com/java/j...

[4] 速学堂:https://www.sxt.cn/Java_jQuer...

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值