封装

在如何理解面向对象这篇文章中,提到所谓的封装就是“功能都给你做好了,你不必去理解它是怎么写出来的,直接使用即可。”。但你得清楚一点,那就是这句话是相对于使用者来说的,而作为开发者,封装就得我们自己来干。
那么作为开发者,我们应该如何去封装呢?其实你应该反过来问,他们应该如何去使用,这样一想会简单很多,作为使用者,自然是希望越简单越好,也就是说,一些复杂的东西,我们不应该让使用者去操作,那也就是说我们应该把复杂的,以及不必要的参数给它封死,不让使用者去操作。
为什么不让使用者去操作?
因为往往使用者是不太专业的,如果暴露太多的接口给他们,就很有可能出现一些稀奇古怪的问题,好比一个不会做水煮鱼的,如果让他去做那肯定是不好的,那怎么办,给他买一包水煮鱼的调料,让他直接放进锅里就好,这样就减少了不必要的麻烦。我们封装程序也是这样,把复杂的代码封死,不让操作者去操作,以免出错。
比如下面这个例子:
class Average{
private int[] fractions = new int[3]; //分数
private int average = 0; //平均分
public void setFraction(int[] fraction){
fractions = fraction;
}
public double getAverage(){
for(int cell:fractions){
average += cell;
}
return (double) (average / fractions.length);
}
}
class app{
public static void main(String[] args){
int[] a = {50,40,50};
Average average = new Average();
average.setFraction(a); //设置分数
double n = average.getAverage(); //获取平均分
System.out.println(average.average); //报错
System.out.println(n); //46.0
}
}
提示:Java通过private设置私有变量,通过public将变量设置成公开的。
这里我们之所以将分数和平均分设置成私有变量是为了防止使用者误操作,而且也不必让使用者知道有这么一个变量,只需要让使用者知道怎么去设置分数,和获取平均分就好了。
当然这只是一个很基础的封装,如果想封装出一个好的程序,还得多费一些心思。
继承
拿猫和狗来说,它们都是动物,而且它们有一些共同点,比如:名字,年龄,声音,吃等。把这段话写成代码就是下面这个样子。
class Animal{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
}
class Cat extends Animal{
public void voice(){
System.out.println(super.getName() + " 喵");
}
public void eat(){
System.out.println(super.getName() + " fish");
}
}
class Dog extends Animal{
public void voice(){
System.out.println(super.getName() + " 汪");
}
public void eat(){
System.out.println(super.getName() + " Bone");
}
}
class app{
public static void main(String[] args){
Cat cat = new Cat();
cat.setName("猫大王"); //Cat本身没有setName方法,但是它的基类有,所以java解析器会到Cat的基类那里拿
cat.voice();
Dog dog = new Dog();
dog.setName("大黑");
dog.setAge(13);
dog.voice();
System.out.println(dog.getName() + dog.getAge());
}
}
------Output------
猫大王 喵
大黑 汪
大黑13
提示:Java通过extends关键字来实现继承,父类中通过private定义的变量和方法不会被继承,也就是你不能在子类中直接操作父类通过private定义的变量以及方法。
在上面代码中,我们可以看到,Cat和Dog并没有定义setName、setAge、getName、getAge方法,但是我们依然可以在Cat和Dog类中使用,这是因为我们通过extends关键字继承了Animal类,因此在Animal中定义的变量和方法,我们可以在子类中直接使用,除private定义的变量和方法。
反过来说,姓名和年龄是猫和狗的基本信息也是它们的共同特性。
重写父类方法或变量
一般重写父类方法,是因为你把猫当成是一个基类,而将狗继承自猫类。看似这很好笑,但如果你去翻翻你的代码,这种情况多如牛毛。当然,如果你不需要继承,那就另说了。那么如果碰到这种情况,我们怎么重写基类呢?很简单,在子类中定义一个和父类中一样的方法,如下面这样:
class Animal{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
}
class Dog extends Animal{
public String getName(){
return super.getName() + "2";
}
public void voice(){
System.out.println(super.getName() + " 汪");
}
public void eat(){
System.out.println(super.getName() + " Bone");
}
}
class app{
public static void main(String[] args){
Dog dog = new Dog();
dog.setName("大黑");
System.out.println(dog.getName()); //执行的是Dog中的getName方法
}
}
提示:通过super可以在子类中直接调用父类的方法以及变量,通过this调用当前类。
我觉得把这叫做重写不太好,因为如果从本质来讲,它不算重写,只是Java寻找变量以及方法的规则罢了。Java会先看一下,自己身上有没有某个变量或方法,如果没有,它会接着到父类中找,如果父类中还是没有,那么它又会到更上一级中找,如果一直找上去都没有,那么才报错。
在重写父类时,需要注意一下,重写时,方法的返回值类型必须和父类中定义的一致,如果是数字类型,只要重写时类型不大于父类中定义的,那么也是可以的。比如下面这样就会报错
class Animal{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
class Dog extends Animal{
public int getName(){ //和父类中的getName返回值不同,报错
return 123;
}
}
class app{
public static void main(String[] args){
Dog dog = new Dog();
System.out.println(dog.getName());
}
}
另外还需要注意,如果重写时,和父类中的参数不一致,则会发生意想不到的事,比如下面这个
class Animal{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(String hello){
return this.name + hello;
}
}
class Dog extends Animal{
public String getName(){
return "123";
}
}
class app{
public static void main(String[] args){
Dog dog = new Dog();
dog.setName("大黑");
System.out.println(dog.getName("hello"));
}
}
------Output------
大黑hello
可以看到当我们给getName传达了参数时,执行的是Animal中的方法,而非Dog中的getName方法,也就是说如果参数不一致最后执行的可能就不是重写的那个方法。另外也不可将父类公开的方法或变量改成私有(如将public改成private),否则也会报错,我估计是Java有一套覆盖规则,如果没有达到条件就不会进行覆盖。
总结来,覆盖父类方法或变量时,对其只能更宽松,而反过来则不行。
多态
先来几个例子,再讲理论
class Animal{
public int age = 5;
public int getAge(){
return age;
}
}
class Dog extends Animal{
public int age = 8;
public int getAge(){
return age + 2;
}
}
class app{
public static void main(String[] args){
Animal dog = new Dog();
System.out.println(dog.age);
}
}
------Output------
5
看Animal dog = new Dog();这么一句话,可以发现它们的类型并不一样,但却可以正常运行,之所以可以运行是因为,Dog类是Animal的子类,而父类是包括子类的。我们说动物,那么狗是不是就是动物中的一员呢,这是肯定的,而这里之所以如果运行也正是这个理。
不过需要注意一下,通过这种方式创建的对象,在获取实例变量时,获取到的是父类中的实例变量,如果是方法,则看子类中是否存在和父类中同名的方法,如果存在则使用子类中的方法,但是如果子类中有某个方法,而父类中没有,那么就会报错。如下这段代码就会报错
class Animal{
public int age = 5;
public int getAge(){
return age;
}
}
class Dog extends Animal{
public int age = 8;
public int getAge(){
return age + 2;
}
public setAge(int a){
this.age = a;
}
}
class app{
public static void main(String[] args){
Animal dog = new Dog();
System.out.println(dog.setAge(5));
}
}
因为父类中没有setAge这个方法,因此会报错。
也就是说,通过这种方式来写,只能达到覆盖方法的效果,没有其他的功能。
这里所谓的多态,在程序中你可以理解成,一个方法,它可以有不同的效果,那怎么实现不同的效果呢?在java中通过切换类型来实现(不一定正确)。
多态有什么用?
还是再来看几个例子吧
class Animal{
public int age = 5;
public int getAge(){
return age;
}
}
class Dog extends Animal{
public int getAge(){
return age + 2;
}
}
class Cat extends Animal{
public int getAge(){
return age + 3;
}
}
class app{
public static void main(String[] args){
Animal dog = new Dog();
Animal cat = new Cat();
System.out.println(dog.getAge());
System.out.println(cat.getAge());
}
}
------Output------
7
8
可以看到,它会根据自身执行不同的方法。不过话说回来,这并不能代表什么,毕竟我们按照正常情况来创建,效果也可以一样,不过还真有它的用武之处,比如下面这段代码
class Animal{
public int age = 5;
public int getAge(){
return age;
}
}
class Dog extends Animal{
public int getAge(){
return age + 2;
}
}
class Cat extends Animal{
public int getAge(){
return age + 3;
}
}
class app{
public static void main(String[] args){
Animal[] animals = new Animal[2];
animals[0] = new Dog();
animals[1] = new Cat();
System.out.println(animals[0].getAge());
System.out.println(animals[1].getAge());
}
}
------Output------
7
8
这段代码和上面一段差不多,不过这段代码中用的是一个数组,这种情况就比较适合使用多态了,不然好像没有其他办法来弄了吧(初学java,不太懂)。在这里面多态不仅仅只是指一个方法有不同的效果,在这里还指类型的多样性。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# java
# 封装
# 继承
# 多态
# Java轻松掌握面向对象的三大特性封装与继承和多态
# 浅谈Java封装、继承、多态特性
# Java面向对象基础知识之封装
# 多态和抽象
# JAVA回顾:封装
# 详细理解JAVA面向对象的封装
# 抽象
# 详解java封装继承多态
# Java面向对象编程(封装/继承/多态)实例解析
# Java封装、继承、多态三大特征的理解
# Java OOP三大特征之封装继承与多态详解
# 类中
# 重写
# 报错
# 的是
# 子类
# 大黑
# 这段
# 就会
# 可以看到
# 这种情况
# 是一个
# 几个
# 是因为
# 让他
# 你不
# 也就是说
# 如果没有
# 我们应该
# 它会
相关文章:
如何正确选择百度移动适配建站域名?
建设网站制作价格,怎样建立自己的公司网站?
Python多线程使用规范_线程安全解析【教程】
如何通过网站建站时间优化SEO与用户体验?
网页设计网站制作软件,microsoft office哪个可以创建网页?
制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?
如何规划企业建站流程的关键步骤?
公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?
制作农业网站的软件,比较好的农业网站推荐一下?
海南网站制作公司有哪些,海口网是哪家的?
济南网站制作的价格,历城一职专官方网站?
免费制作小说封面的网站有哪些,怎么接网站批量的封面单?
太原网站制作公司有哪些,网约车营运证查询官网?
建站之星代理如何优化在线客服效率?
如何选择高效可靠的多用户建站源码资源?
建站主机SSH密钥生成步骤及常见问题解答?
网站设计制作公司地址,网站建设比较好的公司都有哪些?
建站主机选购指南与交易推荐:核心配置解析
宝华建站服务条款解析:五站合一功能与SEO优化设置指南
建站之星图片链接生成指南:自助建站与智能设计教程
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
内部网站制作流程,如何建立公司内部网站?
网站制作模板下载什么软件,ppt模板免费下载网站?
黑客如何通过漏洞一步步攻陷网站服务器?
Android使用GridView实现日历的简单功能
合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?
如何高效完成独享虚拟主机建站?
如何通过西部数码建站助手快速创建专业网站?
建站主机服务器选型指南与性能优化方案解析
广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的?
网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?
如何制作网站标识牌,动态网站如何制作(教程)?
重庆网站制作公司哪家好,重庆中考招生办官方网站?
宝塔面板创建网站无法访问?如何快速排查修复?
免费网站制作appp,免费制作app哪个平台好?
零基础网站服务器架设实战:轻量应用与域名解析配置指南
如何快速选择适合个人网站的云服务器配置?
建站主机如何选?性能与价格怎样平衡?
怀化网站制作公司,怀化新生儿上户网上办理流程?
建站VPS选购需注意哪些关键参数?
制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?
建站之星在线版空间:自助建站+智能模板一键生成方案
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
建站IDE高效指南:快速搭建+SEO优化+自适应模板全解析
建站主机选购指南:核心配置与性价比推荐解析
青岛网站建设如何选择本地服务器?
h5在线制作网站电脑版下载,h5网页制作软件?
建站之星CMS五站合一模板配置与SEO优化指南
教育培训网站制作流程,请问edu教育网站的域名怎么申请?
哈尔滨网站建设策划,哈尔滨电工证查询网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。