为了账号安全,请及时绑定邮箱和手机立即绑定

Java面向对象编程——封装和继承

标签:
Java

面向对象是编程的重点,涉及到类的封装继承抽象多态接口的设计等。其中,封装、继承、多态是面向对象的三大特征。MVC架构中的"Model"部分的设计,实际上就是基于对象的设计,就是面向对象编程。而面向对象编程,是一门较深的学问。面向对象编程的方法可以通过具体实例总结,而在不同的具体环境及需求中,对象设计及方法的应用,是需要长期的实践经验来积淀。通过不断熟练面向对象编程思维,权衡功能以尽可能实现需求,来完善代码,进一步增强代码可读性和简洁性、实用性。因此,“武功秘诀”虽简单,但练就绝非一朝一夕。

本文基于Java面向对象编程,引用了一些实例及相应方法,以尽可能总结Java面向对象编程封装继承的要素。

封装

  • 封装:是一种面向对象编程方法,对类的具体实现细节部分进行包装隐藏,只暴露方法接口,但方法的实现不完全暴露给用户。

  • 前提:正确地表达现实生活中的问题,并保证代码的拓展性和可维护性。

  • 整体思路:是将把代码分成两个部分:接口实现,以类的形式进行封装。其中,接口将涉及和外部的交互,属于对用户暴露的部分,应该保持稳定,因此修改维护代码的时候,可以只改变内容而不改变接口,使用方式不变;内部实现不需要暴露给外部用户,在接口功能不被影响的前提下,可以随意修改和重构

  • 封装方法:对类的内部状态的访问进行控制,根据需求只提供该提供的信息。采用privatefinal等修饰符对相应成员变量或方法进行访问或修改控制,再用gettersetter等方法作为接口,赋予私有变量的可读或可写权限。final限制了setter的使用,进一步防止私有变量被修改。

  • 原因:可以防止用户使用的时候出错,或降低出错的可能。用户在调用编写的类的时候,有一定概率会出错,不能低估用户的想象力。但在团队合作中,必须考虑什么事情该自己承担,什么是用户的责任,什么是自己的责任。因此设计产品的时候,优先设计为private隐藏信息,再考虑是否有暴露出去的必要,根据具体需求改成public或其他访问权限。

  • 原则高内聚,低耦合,良好的封装是解耦的基础
    低耦合:保留必须的方法
    高内聚:大部分具体实现代码可以修改

  • 应用场景
    1.发现代码有问题,需要进行错误修正优化算法来改变实现
    2.发展新能力,通过修改方法内容来实现,例如读取文件的方式可以从txt文档读取,发展为从word文档中读取,或从本地文件读取发展为网络信息读取

封装代码实例

import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;public class News {    private String title;                                         
    private String content;                                       //private限制了外部访问
    
    public News(){}                                               //缺省构造函数

    public News(String title,String content) {                    //构造函数初始化成员变量
        this.title = title;        this.content = content;
    }    //可改变title和content,相当于一种setter方法
    //title和content被final修饰时,此方法会报错
    public void read(String fileUrl) throws IOException{          
        try {            //从Url读取内容
            BufferedReader  reader = new BufferedReader(new FileReader(new File(fileUrl)));
            title = reader.readLine();                            //赋值给title
            content = reader.readLine();                          //赋值给content
        }        catch (IOException e) {
            System.out.println("新闻读取出错");                     //异常抓取
        }
    }    public String getTitle() {                                    //getter方法,为title提供可读接口
        return title;
    }    public String getContent() {                                  //getter方法,为content提供可读接口
        return content;
    }    //控制如何显示,显示格式,相当于一种getter方法
    public String display() {        return title + "\n" + content;
    }
}

测试代码

import java.io.IOException;public class Main {    public static void main(String[] args) throws IOException {
        News news = new News("abc","blabla");
        System.out.println(news.display());
        news.read("");
        System.out.println(news.display());
    }
}

测试结果

abc
blabla
新闻读取出错
  • 总结尽可能向用户暴露更少的信息
    原因
    1.给予用户的接口越少,他操作时基于的东西就越少,他需要知道的知识越少,这个程序在使用上就越简洁,使用成本越低
    2.暴露的代码越少,客户依赖于我们写的代码就会越少,我们在修改维护时就可以进行更灵活的更改。而任何暴露给用户的内容,基本上是不能更改的,或者说更改暴露内容是万不得已的选择

继承

  • 继承:是Java面向对象编程技术的一块基石,因为他允许创建分等级层次的类,即分层

  • 方法:在声明子类的时候,通过关键字extends表达继承

  • 特性
    1.子类拥有父类非private的成员变量和方法
    2.子类可以拥有自己的成员变量和方法,即子类可以对父类进行扩展
    3.子类可以重新实现父类的方法,override
    4.Java只支持单继承,即只能有一个父类,省去了多继承带来的麻烦(C++不一样,可以多继承)
    5.super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类
    6.this关键字:指向自己的引用
    7.final <类>:防止类被继承

  • 关系is-a
    父类具有子类的公共变量和方法,子类是更具体的父类,子类继承父类的特征和行为,使得子类对象具有父类对象的特征和方法,并拓展额外的功能。因此设计时将对象的公共部分抽象出来,从子类抽象出父类,会更直接更符合设计的直觉

  • 原则:没有重复代码

  • 构造方法:先有的父类,才有的子类,因此要先初始化父类,在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。
    其中,子类不能继承父类的构造器(构造方法或者构造函数),如果父类的构造器带有参数,则必须在子类的构造器中显示地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类的构造器没有参数,则在子类的构造器中不需要使用super关键字调用父类构造器,系统会自动调用父类的无参构造器(并不是不用)

父类代码实例

public class News {
    protected String title;         //可被子类访问
    protected String content;    //无参构造器
    public News(){}    // 构造的自由和责任交给用户
    public News(String title, String content) {        this.title = title;        this.content = content;
    }    public String getTitle() {        return title;
    }    public String getContent() {        return content;
    }    // 控制如何显示
    public String display() {        return title + "\n" + content;
    }
}

子类代码实例

import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;public class FileNews extends News{    public FileNews(String title ,String content) {        super(title, content);                  //调用父类构造函数
    }    public FileNews() {}                        //默认有个super()

    public void read(String url) throws IOException {        try {
            BufferedReader reader = new BufferedReader(new FileReader(new File(url)));
            title = reader.readLine();          // 读取title
            reader.readLine();                  // 跳过空行
            content = reader.readLine();        // 读取content
        }        catch (IOException e) {
            System.out.println("新闻读取出错");  // 异常处理
        }
    }    public String display() {                   // display()方法的override
        return super.display() + "from 子类";
    }
}

测试代码

import java.io.IOException;public class Main {    public static void main(String[] args) throws IOException {
        News news = new News("abc","父类");
        System.out.println(news.display());

        FileNews fileNews = new FileNews("123","子类");
        System.out.println(fileNews.display());
    }
}

测试结果

abc
父类
123:子类
  • 总结:继承为了继承成员变量,可能会牺牲private和final,protected修饰,但会牺牲部分安全性(只能用注释声明告诉用户不要修改它),因此这又是一个权衡的过程与责任的分配,因此在写类的时候要考虑其是否将来会被继承,来决定变量的访问限制。



作者:迷路的丸子
链接:https://www.jianshu.com/p/db392c22b808


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
205
获赞与收藏
1007

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消