❣博主主页: 33的博客❣
▶文章专栏分类: Java从入门到精通◀
🚚我的代码仓库: 33的代码仓库🚚
1.前言
对于面向对象程序三大特性:封装、继承、多态。这篇文章将会详细讲解到如何实现封装、继承、多态,以及具体的应用。
本章重点
掌握封装的概念,如何实现封装,包的概念,继承的概念,为什么要继承,继承的相关语法,子类构造方法等等。
2.封装
对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
2.1如何实现封装
class Student {
private String name;//用private权限修饰可以实现,此时name只能在当前类中使用
private int age;
private String sex;
}
那么这个时候我如果想在其他类值获取被private修饰的成员变量的值,该如何修改呢?其实,只需要设置set和get方法,就可以在其他类中访问了。
快捷生成方式如下:
2.2 访问限定符
Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:
public:可以理解为一个人的外貌特征,谁都可以看得到
default: 对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了
private:只有自己知道,其他人都不知道
protected:子类或者同一类都可以访问
2.3包的概念
在上面四种权限中,我们可以看到多次提到了包,那么什么是包呢?其实包简单来说就是一个文件夹。为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件下,也可以对某个文件夹下的音乐进行更详细的分类。
包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
2.3.1导入包中的类
其实在之前,认识键盘输入的时候,我们已经接触过导入包中的类了:
import java.util.Scanner;
如果我们需要导入util中的其他类也导入,格式如下:
import java.util.*;
虽然导入了util这个文件底下的所有类,但在Java中用到那个类才会导入它。
但这样导入一个包下所有类有弊端l,两个包底下出现了同一个类就不能编译:比如util包和sql包下都有Date类,当调用Date类的时候,编译器也不知道用谁的。
import java.util.*;
import java.sql.*;
Date date1 = new Date();
Date date1 = new Date();
我建议显式的指定要导入的类名. 否则容易出现冲突的情况。
2.3.2自定义包
基本规则
- 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
- 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式例如:(com.baidu.www)
- 包名要和代码路径相匹配. 例如创建代码(com.baidu.www)的包,那么会存在一个对于路径com/baidu/www
- 如果一个类没有 package 语句, 则该类被放到一个默认包中
操作步骤:
1. 在 IDEA 中先新建一个包: 右键 src -> 新建 -> 包
2. 在弹出的对话框中输入包名,例如com.baidu.www,下图是按一层一层进行显示
3.继承
3.1为什么要继承
Java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑。
比如:狗和猫,它们都是一个动物。
// Dog
public class Dog{
string name;
int age;
f
loat weight;
public void eat(){
System.out.println(name + "正在吃饭");
}
public void sleep(){
System.out.println(name + "正在睡觉");
}
void Bark(){
System.out.println(name + "汪汪汪~~~");
}
}
// Cat
public class Cat{
string name;
int age;
f
loat weight;
public void eat(){
System.out.println(name + "正在吃饭");
}
public void sleep()
{
System.out.println(name + "正在睡觉");
}
void mew(){
System.out.println(name + "喵喵喵~~~");
}
}
观察上面代码,我们会发现它们都存在大量相同的属性和方法
狗:
string name;
int age;
public void eat()
public void sleep()
void Bark()
猫:
string name;
int age;
public void eat()
public void sleep()
void mew()
那能否将这些共性抽取呢?面向对象思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。
3.2继承的概念
继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。
3.3继承的语法
在Java中要表示类之间的继承关系,需要借助extends关键字,具体如下:
修饰符 class 子类 extends 父类 {
// ...
}
注意
- 子类会将父类中的成员变量或者成员方法继承到子类中了。
- 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了。
3.4父类成员访问
在继承体系中,子类将父类中的方法和字段继承下来了,那在子类中能否直接访问父类中继承下来的成员呢?
3.4.1子类中访问父类的成员变量
1.访问不同名的成员变量
//父类
public class Base {
int a;
int b;
}
//子类
public class Derived extends Base{
int c;
public void method(){
a = 10; // 访问从父类中继承下来的a
b = 20; // 访问从父类中继承下来的b
c = 30; // 访问子类自己的c
}
}
2.访问同名的成员变量
public class Base {
int a;
int b;
int c;
}
public class Derived extends Base{
int a; // 与父类中成员a同名,且类型相同
char b; // 与父类中成员b同名,但类型不同
public void method(){
a = 100; // 访问父类继承的a,还是子类自己新增的a?
b = 101; // 访问父类继承的b,还是子类自己新增的b?
c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
// d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
}
}
那如在同名的情况下,我想访问父类的成员,该怎么办呢?可以使用super关键字
public class Base {
int a;
int b;
int c;
}
public class Derived extends Base{
int a; // 与父类中成员a同名,且类型相同
char b; // 与父类中成员b同名,但类型不同
public void method(){
super.a = 100; // 访问父类继承的a
super.b = 101; // 访问父类继承的b
c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
// d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
}
}
在子类方法中 或者 通过子类对象访问成员时:
- 如果访问的成员变量子类中有,优先访问自己的成员变量。
- 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
- 如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
- 如果想访问父类成员,可以使用super关键字。
- 成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。
3.5子类构造方法
父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。
//Animal
public String name;
public int age;
public String color;
public void eat(){
System.out.println(this.name+"正在吃饭");
}
public Animal(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
//Cat
public class Cat extends Animal{
public Cat(String name, int age, String color) {
super(name, age, color);//初始化父类构造方法
}
public void mew(){
System.out.println("喵喵喵~~~");
}
}
如果我父类没有构造方法,子类也不调用,会报错吗?答案是不会的,因为父类没有构造方法会默认生成一个,此时就会调用生成的构造方法,只不过看不见。注意
- 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构
造方法- 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的
父类构造方法调用,否则编译失败。- 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
- super(…)只能在子类构造方法中出现一次,并且不能和this同时出现
3.6super和this
super和this都可以在成员方法中用来访问:成员变量和调用其他的成员函数,都可以作为构造方法的第一条语句,那他们之间有什么区别呢?
【相同点】
- 都是Java中的关键字
- 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
- 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
【不同点】
- this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用。
- 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性。
- 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现。
- 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有。
3.7继承方式
在现实生活中,事物之间的关系是非常复杂,灵活多样,比如:
Java中的几种继承:
单继承:
public class A{
}
public class B extend A{
}
多层继承
public class A{
}
public class B extend A{
}
public class C extend B{
}
注意:
Java中不支持多继承,指的是不支持一个类继承多个父类。
但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了。
如果想从语法上进行限制继承, 就可以使用 final 关键字。
3.8final 关键字
final关键可以用来修饰变量、成员方法以及类。
1.修饰变量:表示常量
final int a = 10;//此时a是一个常量不能再改变
- 修饰类:表示此类不能被继承
final public class Animal {
}
3.9继承和组合
和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。
继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物
组合表示对象之间是has-a的关系,比如:汽车
例如
// 轮胎类
class Tire{
//....
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
//组合
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}
// 继承:奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}
4.总结
本篇文章主要讲了有关封装和继承的相关知识点,在下一篇文章中博主将继续更新多态的相关知识点,感兴趣的同学可以关注博主哦。文章来源:https://www.toymoban.com/news/detail-845239.html
下期预告:多态
文章来源地址https://www.toymoban.com/news/detail-845239.html
到了这里,关于【Java初阶(六)上】封装 继承 多态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!