Java面向对象程序开发——面向对象的封装、继承、多态
面向对象的封装、继承、多态
本文来自老师授课内容,已获得老师同意在此当做本人学习笔记记录
文章目录
紧接上一篇Java面向对象基础
类和对象
类:是一组相关属性和行为的集合
对象:是一类事物的具体体现。对象是类的一个实例,必然具备该类事物的属性和行为
类是对一类事物的描述,是抽象的。
对象是一类事物的实例,是具体的。
类是对象的模板,对象是类的实体。
public class Test {
public static void main(String[] args) {
//实例化: 类名 对象名 = new 类名();
Phone huawei = new Phone();
System.out.println(huawei.brand);
System.out.println(huawei.price);
System.out.println("--------------------------------------");
//成员变量赋值
huawei.brand = "mate40";
huawei.price = 2000;
System.out.println(huawei.brand);
System.out.println(huawei.price);
huawei.call("导员"); //调用成员方法
}
}
class Phone{ //类
String brand;//相关属性,成员变量:类中方法外
int price;//相关属性
public void call(String person) {//行为的集合,成员方法,和以前定义的方法几乎一样,只是把static去掉了
System.out.println("给"+person+"打电话");
}
}
封装
面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。
封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类数据,必须通过指定方式。
将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问
private int name = 10; //成员变量
//getter & setter 一种封装
public int getName() {
return name;
}
public void setName(int name) {
if(name > 0 ) {this.name = name;}
else {this.name = 11;}
}
封装的好处
加强了程序代码的安全性。
适当的封装可以提升开发效率,让代码更容易理解与维护,也加强了代码的安全性
Java中的四种访问控制符是:
-
private(私有的):表示只能在本类中访问,其他类无法访问。
-
default(默认的):表示只能在同一包中访问,其他包无法访问。
-
protected(受保护的):表示可以被本类、同一包中的类和不同包中的子类访问,其他不同包的类无法访问。
-
public(公共的):表示可以被任何类、任何包中的类访问。
这些控制符控制了类、方法、属性的访问范围,提高了程序的安全性和可维护性。在设计程序时,应该根据需要选择适当的访问控制符。
封装的实现步骤
一般对成员变量使用private(私有)关键字修饰进行隐藏,private修饰后该成员变量就只能在当前类中访问。
提供public修饰的公开的getter、setter方法暴露其取值和赋值。
定义类定义属性、方法,需要首先指明访问权限
//正确写法
public class Student {
// 定义属性时使用private权限
private String name;
private int age;
private String grade;
public Student() {
super();
}
public Student(String name, int age, String grade) {
super();
this.name = name;
this.age = age;
this.grade = grade;
}
// 需要为每一个私有的属性提供一对set/get方法,让其他类使用
// 定义方法时使用public权限
public void showInfo() {
System.out.println("学生姓名:" + name + ",年龄:" + age + ",班级:" + grade);
}
public String getName() {
return name;
}
public void setName(String name) {
// this.name = name;
if (name != null && !name.trim().equals("")) {
this.name = name;
} else {
System.out.println("姓名不能为空");
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
// this.age = age;
if (age >= 6 && age <= 18) {
this.age = age;
} else {
System.out.println("年龄不合法(应在6~18岁之间)");
}
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
// this.grade = grade;
if (grade != null && !grade.trim().equals("")) {
this.grade = grade;
} else {
System.out.println("班级不能为空");
}
}
}
封装是面向对象的三大特征之一,合理隐藏,合理暴露。一般会把成员变量使用private隐藏起来
一般封装通过getter和setter方法暴露其访问体现出来
对应的测试类:
public class TestStudent {
public static void main(String[] args) {
Student stu = new Student("Tom", 20, "男");
stu.showInfo(); stu.setAge(8);
stu.setAge(30); stu.showInfo();
}
}
继承
子类能继承父类的属性和方法 extends
继承就是java允许我们用extends关键字,让一个类和另一个类建立起一种父子关系。(子类 extends父类)
提高代码复用性,减少代码冗余,增强类的功能扩展性
子类继承父类即拥有父类定义的所有属性和方法,同时要增加自己的属性和方法
1、Java是单继承的(一个孩子只有一个父亲,一个父亲可以有多个孩子),一个父类可以有多个子类
2、可以有多级继承,祖宗类java.lang.Object
Java中子类更强大
1、提高代码的复用性
2、是多态的前提
案例:
public class Emp {
//父类
public void clock() {
System.out.println("打工人上班打卡");
}
}
①、子类创建对象时,在构造方法中必须先调用父类的构造方法
②、使用super() 调用父类构造方法
③、调用父类无参构造方法 super() 可以省略
④、使用在子类构造方法中 this()和super()不能同时出现
public class Worker extends Emp{
//子类 只允许单继承
public void shift() {
System.out.println("工人需要倒班");
}
}
通过测试验证子类继承父类后拥有父类定义的所有属性和方法
public class 继承测试 {
public static void main(String[] args) {
Worker worker = new Worker();
worker.clock();
worker.shift();
}
}
子类实例化过程
我们刚才(案例一中)在定义类时并没有加属性
子类在创建对象的过程就叫实例化
Student称为子类(派生类),People称为父类(基类或超类)
作用:当子类继承父类后,就可以直接使用父类公共的属性和方法了,而且是必须调用父类的
public class Student extends People { }
接着以上面的案例为例子:
public class Emp {
//父类
String name;
double sal;
public Emp() {
//super();
//调用父类的无参构造方法
System.out.println("Emp无参构造方法执行了");
}
public Emp(String name, double sal) {
super();
this.name = name;
this.sal = sal;
}
public void clock() {
System.out.println("打工人上班打卡");
}
}
Emp无参构造方法执行了这句话被打印了出来
接下来是子类
public class Worker extends Emp{
//子类创建对象时,在构造方法中必须先调用父类的构造方法
//使用super() 调用父类构造方法
//调用父类无参构造方法 super() 可以省略
//使用在子类构造方法中 this()和super()不能同时出现
String workshop;
public Worker() {
//super();
}
//子类拥有的属性 两部分继承 继承父类和自己定义的
public Worker(String name, double sal, String workshop) {
super(name, sal); //父类的属性调用父类有参构造方法初始化
this.workshop = workshop; //自己的属性代码完成
}
public void shift() {
System.out.println("工人需要倒班");
}
}
在上面声称有参构造方法时要选择有参的
继承中构造方法的访问特点
1、子类中所有的构造方法默认都会访问父类中的无参的构造方法
2、因为子类会继承父类中的数据,可能还会使用父类中的数据,所以子类初始化之前,需要对父类进行初始化。
3、每个子类构造方法的第一句默认都是:super()
如果父类中没有无参构造方法,只有带参构造方法,怎么办?
1、通过super关键字显示调用父类的有参构造方法
2、父类中自己单独定义一个无参构造方法
JavaBean
JavaBean的思维导图如下图所示:
标准代码,一种标准规范
class A{
//成员变量
//构造方法:一定有无参的,建议有有参的
//成员方法
//getter & setter
}
多态
多态是一个行为有多个不同的表现形式。指对象可以有多种形态
小明同学是个学生,同时他是个人。既有学生的形态又有人的形态,一个对象有多种形态就是对象的多态性。
父类名 对象名 = new 子类名()
接口名 对象名 = new 实现名()
多态的前提:
1、有继承extends
或实现implements
(有继承/实现关系)
2、方法重写,如果方法一样就没意义 (有方法重写(多态侧重行为多态))
3、父类引用指向子类对象(有父类引用指向子类对象)
案例一
USB接口有void open(), close()
类Mouse实现 USB接口,click
类KeyBoard实现 USB接口,type
public class Test {
public static void main(String[] args) {
USB obj = new Mouse();//接口名 对象名 = new 实现名()
//父类名 对象名 = new 子类名()
obj.open();
}
}
interface USB {
void open();
void close();
}
class Mouse implements USB{
@Override
public void open() {
System.out.println("open mouse");
}
@Override
public void close(){
System.out.println("close mouse");
}
public void click(){
System.out.println("点击鼠标");
}
}
class KeyBoard implements USB {
@Override
public void open() {
System.out.println("open keyBoard");
}
@Override
public void close() {
System.out.println("close keyBoard");
}
public void type(){
System.out.println("敲击键盘");
}
}
电脑使用鼠标键盘 Laptop
public class Test {
public static void main(String[] args) {
Laptop lp = new Laptop();
USB usb = new Mouse(); //多态
lp.useUSB(usb);
}
}
interface USB {
void open();
void close();
}
class Mouse implements USB{
@Override
public void open() {
System.out.println("open mouse");
}
@Override
public void close(){
System.out.println("close mouse");
}
public void click(){
System.out.println("点击鼠标");
}
}
class KeyBoard implements USB {
@Override
public void open() {
System.out.println("open keyBoard");
}
@Override
public void close() {
System.out.println("close keyBoard");
}
public void type(){
System.out.println("敲击键盘");
}
}
class Laptop{
public void useUSB(USB usb) { //电脑使用USB
usb.open();
if(usb instanceof Mouse) {//instanceof的作用:判断前面对象usb能不能当后面类型的实例Mouse
Mouse m = (Mouse)usb; //类型转换,调用特有方法
m.click();
}
else {
KeyBoard keyBoard = (KeyBoard)usb;
keyBoard.type();
}
usb.close();
}
}
案例二
1、先定义一个接口
public interface Run {
void print();
}
2、接着写实现类
实现开宾利
public class Bcar implements Run{
//宾利
@Override
public void print() {
// TODO 自动生成的方法存根
System.out.println("今天开宾利");
}
}
实现开大众
public class Dcar implements Run{
//大众
@Override
public void print() {
// TODO 自动生成的方法存根
System.out.println("今天开大众");
}
}
现在代码中有实现关系,有方法的重写实现
要有向上的转型——引用数据类型转换
3、再新建一个测试类
public class 多态测试 {
public static void main(String[] args) {
Run run = new Dcar();
run.print(); //调用重写方法出现多态
run = new Bcar(); //给run变量重新赋值
run.print();
}
}
下面我们看一下多态的优点:易于扩展
增加新代码,老代码不需要改动
刚才写了两辆车,一辆宾利、一辆大众,接下来我们再加一个能力,让车能开
通过方法的形参体现需要
需要的是能力——接口
public class Car {
//需要开车的能力
public void carRun(Run run){
System.out.println("我已经准备好开车");
run.print();
}
}
多态优点测试
public class 多态优点测试 {
public static void main(String[] args) {
Car car = new Car();
car.carRun(new Dcar());
}
}
静态关键字
Java中的关键字是具有特殊含义的单词或标识符,它们已经被Java语言用作它们原有的含义,不能用于其他目的。
- class:定义一个类
- public:定义公共的类、方法或属性
- private:定义私有的方法或属性
- protected:定义受保护的方法或属性
- static:定义静态的方法或属性
- final:定义不可更改的常量或方法,或者将类定义为不可继承的
- abstract:定义抽象类或方法
- interface:定义接口
- implements:实现接口
- extends:继承类
- new:创建新的对象
- this:引用当前对象
- super:引用父类对象
- try:定义一个尝试性的代码块
- catch:处理try代码块中抛出的异常
- throw:抛出异常
- throws:声明可能会抛出的异常
- finally:定义一个代码块,无论try代码块是否抛出异常都会执行
- if:定义一个条件语句
- else:定义一个条件语句的可选操作
- switch:定义一个多条件语句
- case:switch语句中的每个条件分支
- break:跳出循环或switch语句
- continue:跳过当前循环的剩余代码并开始下一个迭代
- do:定义一个do-while循环
- while:定义一个while循环
- for:定义一个for循环
- foreach:定义一个增强型for循环
- return:从方法中返回值
- void:定义一个方法不返回值
- true:代表真(布尔类型)
- false:代表假(布尔类型)
- instanceof:判断对象是否是某个类的实例
- import:导入类或包
- package:定义一个包
- synchronized:同步线程
- volatile:定义一个易失性变量
- assert:定义一个断言(用于调试)
以上是Java中的一些关键字及其用法
由于这些关键字已经被Java语言用作其原有的含义,因此不能将它们用于其他目的
静态方法:
- 调用静态方法不需要创建对象,通过[类名.]直接调用
- 静态方法的方法体中不能使用非静态属性(局限,输出就是输出,不能有连接符,不能把所有方法都变成静态的)
- 工具类中的方法一般定义成静态的
静态代码块:
- 静态代码块中的代码只会在类加载时执行一次
- 某一块代码只需要运行一次时
以下是类似的代码例子:
public class Class {
private String name;
private int age;
public static String school = "xxx中学";
//静态属性 全类共享 类加载时(第一次使用)创建空间
//定义类时某一个数据只需要一个值定义成静态属性
//静态方法
public static void sing() {
System.out.println("学生在学校要好好学习");
}
//静态代码块
static {
System.out.println("Class 加载了");
}
}
测试类
public class 静态测试 {
public static void main(String[] args) {
Class c1 = new Class();
Class c2 = new Class();
//静态属性通过 [类名.]访问
System.out.println(Class.school);
Class.sing();
}
}
总结
面向对象的三大特点是:封装、继承、多态
封装知识点:
定义类定义属性、方法,需要首先指明访问权限
定义属性时使用private权限
需要为每一个私有的属性提供一对set/get方法,让其他类使用
定义方法时使用public权限
定义完整类步骤 :
1、定义私有属性
2、定义两个构造方法
3、定义set/get方法
4、定义其他方法
set
是赋值的意思setAge
是给年龄赋值get
是获取
get
——直接获取成员变量的值获取的操作set
——就是给我们成员变量赋值操作,赋值的操作.
继承知识点:
类名后面使用extends
继承父类
只允许单继承,只允许有一个父类
子类继承父类即拥有父类定义的所有属性和方法,同时要增加自己的属性和方法
子类创建对象时,在构造方法中必须先调用父类的构造方法
使用super()
调用父类构造方法
调用父类无参构造方法 super()
可以省略
使用在子类构造方法中 this()
和super()
不能同时出现
子类拥有的属性有两部分继承,继承父类和自己定义的
什么情况下使用到继承模式呢?
多个类中存在相同的成员属性或者方法,使用继承模式将每个子类相同代码直接抽取出来存放在父类中。
继承中变量的访问特点
在子类方法中访问一个变量:
子类局部范围找
子类成员范围找
父类成员范围找
如果都没有则报错
即遵循就近原则!
先查找局部变量→当前类中成员属性变量→父类中→如果类中没有该变量的话,直接报错
1、好处:
提高了代码的复用性(多个类相同的成员属性和方法可以放到一个类当中)
提高了代码的维护性(如果方法的代码需要修改,只需修改一处即可)
2、弊端:
继承让类与类之间产生了关系,类的耦合性也增加了,当父类发生变化时候,子类也不得不跟着变化,削弱了子类的独立性。
抽象类知识点:
抽象类 不能创建对象
抽象类 需要子类继承才有意义
抽象类中能定义抽象方法也可以定义非抽象方法
抽象类实际应用中当做模板来使用
抽象类中要包含非抽象的方法,可以让子类继承后直接使用
抽象类要包含抽象方法,让子类继承后去重写
多态知识点:
多态指的是不同对象对同一行为做出的不同响应成为多态
多态出现必要条件:
1、类中要有继承或实现关系
2、要有方法的重写或实现
3、要有向上的转型
调用重写方法出现多态
引用变量存储的是哪一个类的对象就会调用哪一个类的方法
多态优点:易于扩展(增加新代码,老代码不需要改动)
多态缺点:不能使用子类特有功能
多态中的转型
1、向上转型(多态机制)从子到父,父类引用指向子类对象
2、向下转型(强转)从父到子,父类引用转为子类对象
final 作用
final是一种修饰符
修饰变量,变量变常量只能被赋值一次
修饰方法,方法不能被子类重写
修饰类,不能被子类继承
更多推荐
所有评论(0)