面向对象的开发范式其实是对现实世界的理解和抽象的方法,那么,具体如何将现实世界抽象成代码呢?这就需要运用面向对象的三大基本特征,分别是封装、继承和多态。
下面将具体介绍一下这三大特性:
传送门: 【狂神说Java】面向对象三大基本特性
笔记是基于传送门另一端的课程所写的,好的,我们开始:
Java面向对象编程 三大特性
封装、继承、多态
封装
public class Student {
//属性私有 private
private String name;
private int id;
private char sex;
//由于现在为属性私有,main方法中new出来的对象是无法直接对Student类下面的属性进行操作的
//因此,需要提供一些可以操作这个属性的方法:
//也就是 get/set 方法!!!
//其中 get方法用于获取数据;set方法则是设置一个数据作为属性的值
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
//快捷键 alt + insert
public int getAge() {
return age;
}
public void setAge(int age) { //可以对输入的age值 进行一些规则判断
if (age > 120 || age < 0){
this.age = 03;
}else {
this.age = age;
}
}
以及在拥有main方法的Application类下的代码:
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("lyly");
System.out.println(s1.getName());
s1.setAge(17);
System.out.println(s1.getAge());
}
封装的好处:
继承
Java中的类只能单继承
就好比: 一个儿子只能有一个爸爸! 一个爸爸可以有多个儿子
Object类
所有的类 都直接或间接的继承了 Object类
//Ctrl + h 查看
super (与this形成对比)
this.xxx就是反应 在当前类下的属性/方法;
super.xxx则是对应 当前类的父类的属性/方法
而**父类中私有(private)**的东西(也就是属性和方法)无法被继承!
上面的是要围绕讲一下的结果图
Application.java中的代码(非常简单,只有一个对象student的实例化):
package com.oop; import com.oop.extend.*; public class Application { public static void main(String[] args) { Student student = new Student(); } }
运行这个有main方法的类,得到了上图中的两句输出
分别来自父类Person类 与 (继承Person的)子类Student类
而且先输出的Person类中的内容,再是Student类中的内容
Student.java的代码:
package com.oop.extend; //子类继承了父类,就会拥有父类(除private外)全部的方法和属性 public class Student extends Person{ //alt + insert 显现出这个无参构造 public Student() { //这里有隐藏代码----功能是调用父类的无参构造 语句是: // super(); //而且作为调用父类的构造方法,必须在子类构造方法中的最前面第一行写出! System.out.println("子类Student被无参执行..."); } }
(关键点都记录在代码的注释中)
以及
Person.java的代码:
package com.oop.extend; public class Person { public Person() { System.out.println("父类Person被无参执行了!"); } }
这些写一下试一下就可以理解,如果还不能就看一下总结:
方法重写
多态
用代码来理解,会更加深刻
Person.java:
package com.oop.demo4; public class Person { public void run(){ System.out.println("Person run!"); }
这个没啥可说的,就一个父类的run方法
Student.java:
package com.oop.demo4; import com.oop.demo4.Person; public class Student extends Person { @Override //方法重写,重写run方法 public void run() { System.out.println("Student run!!!"); } public void study(){ System.out.println("Studying!"); } }
子类中有对run方法的重写
Application.java:
package com.oop; import com.oop.demo4.Student; import com.oop.demo4.Person; public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 //new Student(); //new Person(); //然而,可以指向的引用类型就不确定了,其父类、Object“祖宗”类都可以 Student student = new Student(); Person s1 = new Student(); Object s2 = new Student(); student.run(); s1.run(); //由于存在子类对run方法的重写,则运行子类重写后的方法! /* s1.study();是不可以跑起来的 所以说,对象能执行哪些方法,主要看对象左边的类型,和右边关系不大! */ //父类Person的对象s1 并无study方法,涉及强制类型转换 ((Student) s1).study(); } }
这里有一些运行的不同尝试,用于对比结果,注释的内容都有说明
instanceof 和 类型转换
instanceof
instanceof 可以去判断 两个类之间是否存在“父子关系”
存在这层“父子关系”就会返回 true 结果
不存在则为false
//可以理解为一个公式:
//System.out.println(x instanceof y);
//用以判断 x实际指向的类型与y类型是否存在父子关系
再new一个对象来看结果:
package com.oop;
import com.oop.demo5.Person;
import com.oop.demo5.Student;
import com.oop.demo5.Teacher;
public class Application {
public static void main(String[] args) {
//可以理解为一个公式:
// System.out.println(x instanceof y);
//用以判断 x实际指向的类型与y类型是否存在父子关系
Person student = new Student();//这里的类相当于由小到大(Student-->Person) 无需强转
//这条关系链是 Object--Person--Student
System.out.println(student instanceof Object);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Teacher);//false
// System.out.println(student instanceof String);//编译错误
}
}
运行结果图:
类型转换
这个得跟着例子来将:
首先,在Student类下面写上一个方法:
ackage com.oop.demo5; public class Student extends Person{ public void study(){ System.out.println("student正在认真学习!"); } }
然后在Application.java下进行操作:
package com.oop; import com.oop.demo5.Person; import com.oop.demo5.Student; import com.oop.demo5.Teacher; public class Application { public static void main(String[] args) { Person wassup = new Student(); // wassup.study(); //这么写是调用不了Student类下面的study方法的! ((Student)wassup).study();//父类-->子类Student,需要强转! //=========================================================== Student stu = new Student(); //new一个Student类型的对象 stu.study(); Person p = stu;//这里将子类Student的对象stu-->父类Person类的对象p,低到高,可以直接转√ // p.study();//报错 此时它已经失去了study()方法... //因此值得注意的是,子类转化成父类,可能丢失一些子类类型时的方法! } }
具体细节都在注释中,需要注意的是:
总的来说,类型转换的存在,就是为了让代码更加简洁!
至此,封装、继承、多态就简单介绍过了,它们的思想就是抽象(一切都有迹可循,并不是不好理解的抽象)
三大特性的简单介绍就是这样了,最主要的抽象的思想就得大家自己在后续的深入学习中以及实战中慢慢培养咯~