Java学习——封装继承多态

封装

什么是封装

下面是来自百度百科的解释

 封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。封装是一种信息隐藏技术,在java中通过关键字private,protected和public实现封装。
&esmp;什么是封装?封装把对象的所有组成部分组合在一起,封装定义程序如何引用对象的数据,封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。 适当的封装可以让程式码更容易理解和维护,也加强了程式码的安全性。

说了一大堆,举个例子,定义下面这个类:

class Box{
	private int width = 10;
	
	public int getWidth() {
		return width;
	}
}

Box里面有属性width,当我们想要获得这个属性时,一般并不通过.width来直接获取。而是用private私有化它后,利用方法getWidth来获取它。这大概可以表示前面那一段高亮的话的意思,就是对于一个类里数据的操作(修改访问)通过方法去实现嘛。


下面有维基百科的一段话:

In object oriented programming languages, encapsulation refers to one of two related but distinct notions, and sometimes to the combination there of
A language mechanism for restricting direct access to some of the object’s components.
A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data

就是说,在面向对象编程中,封装是指两种相关但有区别的概念,有时可能是两者的结合。

  • 它是一种约束那些想要直接获取对象成员的操作的语言机制
  • 它是一种帮助将数据和对数据的操作捆绑在一起的语言结构
    自己理解吧。。。反正它是面向对象编程的很重要的一个特性。

为什么要封装

封装主要目的就是隐藏信息。至于为啥要隐藏信息,可以理解为隐藏了那些复杂的操作过程,只提供简单的接口,这样可以降低各个模块的耦合度,变异单个的进行维护了,不会错一个地方就全错啦。还有就是前面说的增加了安全性,别人不能随便获取和改动你程序里的东西嘛。

封装的详细理解

在Java中实现封装还要仰仗public,protect,private这三个关键字,当然还有默认这三个关键字都没有的情况。它们就是用来约束别人访问的,被它们修饰的变量方法,就会收到不同的约束了。下面的表格抄了这位仁兄的
表格1:

作用域本类本包范围子孙类(只代表其他包中的子孙类)其他包
public可以可以可以可以
protected可以可以可以不可以
default可以可以不可以不可以
private可以不可以不可以不可以

其实public和private还是比较好理解的,一个是所有都可以,一个是只有本类可以。还是来看例子吧:

  • private,挺好理解的,只要被private修饰后,只能在同一个里面使用该方法或者变量。这里还有个要注意的地方(可能是对我来说吧):在java语法里,方法的形参以及方法体中的变量都是局部变量,不能使用访问权限修饰符public,private,protected。所以方法里面不能出现private int i = 1额,会报错的。
    在这里插入图片描述
    在这里插入图片描述
  • default,这里的default是指前面没有public、protected、private,可别真在前面敲一个default。。还是看getWidth()这个方法。前面什么都不加的话这样没有问题吧。
    在这里插入图片描述而如果在另一个包里定义个类。
    在这里插入图片描述
    并让BoxDemo类继承这个类,我们会发现调用getWidth方法是不合法。如果不继承当然更不合法。
    在这里插入图片描述然而将getWidth方法前加上protected后就合法了额。所以protected,表示受保护权限,体现在继承,即子类可以访问父类受保护成员,同时相同包内的其他类也可以访问protected成员。 剩下的public就不用说了,不用继承也可以访问到getWidth方法(偷偷说一句我也是刚才才知道protected原来是这么回事啊,以前还以为protected就是和使命都不加是一样的。。。)
    在这里插入图片描述
    在这里插入图片描述

下面又是从维基上抄的。(博客全靠抄。。)当做引入下面要说的继承吧。

Encapsulation and inheritance
The authors of Design Patterns discuss the tension between inheritance and encapsulation at length and state that in their experience, designers overuse inheritance. They claim that inheritance often breaks encapsulation, given that inheritance exposes a subclass to the details of its parent’s implementation.

就是说提出设计模式的几位大佬在讨论继承和封装的关系时说,继承和封装常常出现对立的状况,因为父类会将自己的操作细节暴露给子类。(自己瞎翻译,建议还是看英文)

继承

还是要从什么是继承,为什么要继承来说?继承继承,在创建一个类时,直接通过继承父类来实现呗,在父类的基础上修改成自己需要的类。为什么,java语言就是支持这种机制呗。Java是单继承,只能有一个直接父类,C++是多继承。(但是为啥我又看到说现在的Java1.8已经可以支持多继承)

相关的关键字

  • final;被final修饰的方法在继承时不可以被重写,但是可以被子类通过.来使用。如果重写了会报这样的错额(还是用的eclipse,什么时候换idea。。)而被final修饰的类则是不可以被其他类继承的。被final修饰的变量则是常量,以后不能改变。感觉就是跟这个单词的意思很像,最后的嘛。以后不能修改啦,不管是变量方法还是类。
    在这里插入图片描述
  • protectedprivate; 前面也已经说过了,private修饰的方法和变量不可以被继承,也就是子类不可以访问到父类的private方法和变量。而protected是可以的。具体情况参见前面的表格1。如果子类调了父类的private方法,可能会报这样的错。
    在这里插入图片描述
  • super ;super两种通用形式,第一种调用超类的构造函数。第二种用来访问被子类的成员隐藏的超类成员
    (1) 第一种,运行下面代码,可以发现在子类的构造函数中只加super()和不加,最后输出都是一样的。这是因为子类构造函数在不加super()的情况下,系统会自动帮你补上super()。也就是说子类必会调父类的构造函数,而一个类至少是继承自Object类,所以它至少是调了Object类的构造函数的。
package learn;

public class BoxDemo extends Pen   {
   public static void main(String[] arg) {
   	new Pen();
   }		
}
class Pen extends Pencil{
   Pen(){
   	super();//可以把这行注释看看
   	System.out.println("Pen重载函数");
   }
}
class Pencil{
   Pencil(){
   	System.out.println("Pencil重载函数");
   }
}

但是如果父类的构造函数都是有参数的话,必须要在子类构造函数里加上super(参数),而不能省略。因为省略时系统只会自动去找无参数的super(),而父类里都是有参数的super(参数),它找不到就会报错。我们来考虑super()可能带来的好处。假设自己是上帝啦,想要造人,这个人现在有身高和体重这两个属性,我写了下面这个类:

class Person{
	private int height;
	private int wight;
	Person(){
		this.wight = 0;
		this.height = 0;
	}
	Person(int height,int wight){
		this.wight = wight;
		this.height = height;
	}

这样,我想造一个人出来的时候就是通过new来实现,假设造一个身高10,体重100的人。就可以通过new Person(10,100)来实现。但是有一天我又想造一个学生,他是人的子类,但是他多了一个属性stunum(学号),这时在构造函数里,我不需要再对这个学生的身高体重进行初始化,只需要对学号进行初始化(这里的初始化指的是this.stunum = stunum;)。因为在Person这个类里,我已经初始化了身高体重了。只要调用super()就可以实现了。这里的初始化还比较简单,可能感觉在Student类的构造函数里在初始化一下身高体重也没啥,但是如果大一点的项目,多等级的继承关系,如果再去自己在去初始化父类里已经初始化好的东西,就比较费时间了。代码如下:

class Student extends Person{
	private int height;
	private int wight;
	private int stunum;
	Student(int height,int wight,int stunum){
		super();//可以把这行注释看看
		this.stunum = stunum;
	}
}

(2) 第二种,可以看下面的代码及运行结果,就是相当于父类的引用嘛。当然private的变量是不可以被访问的:

package learn;

public class BoxDemo extends Pen   {
   public static void main(String[] arg) {
   	new Pen().show();
   }		
}
class Pen extends Pencil{
   private int i = 0;
   public void show() {
   	System.out.println("父类的i是"+super.i);
   	System.out.println("子类的i是"+this.i);
   }
}
class Pencil{
   protected int i = 100;
}

在这里插入图片描述

其他继承相关

  • 超类变量可以引用子类对象
  • 何时调用构造函数
  • 重写和重载
    重载(Overload)是让类以统一的方式处理不同类型数据的一种手段,实质表现就是多个具有不同的参数个数或者类型的同名函数同时存在于同一个类中,是一个类中多态性的一种表现。
    重写(Override)是父类与子类之间的多态性,实质是对父类的函数进行重新定义,如果在子类中定义某方法与其父类有相同的名称和参数则该方法被重写,不过子类函数的访问修饰权限不能小于父类的;若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法,如需父类中原有的方法则可使用 super 关键字。

参考

Java入门经典;
https://blog.csdn.net/qunqunstyle99/article/details/81007712

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值