《仅以此博文纪念2017/03/19 PM 我们的聊天探讨》
这天你提出一个问题,问我为什么要这么做,我不知如何简单的告诉你原因,挂断电话之后我思考了很久 觉得这样解释应该会对你有帮助,也许就会顿悟
TA的问题-------什么是面向对象?
这个问题范围非常的广泛,但是谈及到这个问题,也许很多人想到的是面向对象的基本特征"封装,继承,多态",也有很多人可能还想到了"抽象",但是无论你想到的是三个基本特征还是四个基本特征,完全不会影响你去学习和使用面向对象,以下我用最简单通俗的方法解释一下面向对象入门级别的知识。学习面向对象最主要的问题是,你到底有没有思考过面向对象为什么总是和这几个特点联系在一起的呢?这些特点到底是如何用计算机语言体现的呢??下面谈谈我对面向对象的一些皮毛见解,希望有助于各位入门
其实·面向对象·剖析一下 是"面向"和"对象"两个词汇.那么我认为重在面向,但是且不可忽略其主语--->对象
一 抽象
其实所谓的对象就是一个抽象出来的东西,抽象就是忽略跟当前目标无关的部分,以便充分注意和当前目标有关的部分。
比如,我们要设计一个学生上课管理系统,考察学生(Student)这个对象的时候我们只关心他的学号,姓名,上课状态等而不去关心身高 体重性别这类的信息。我们只关心他上课在做什么,是在听课学习还是摆弄手机打游戏聊天。
抽象包括两个工作 1 对象属性抽象 2 对象行为抽象
所以从上面的学生上课管理系统我们可以抽象出一个对象叫Student ;属性有学号ID ,姓名name ,上课状况 status ;行为方法有 正在做什么doing
现在我们可以有一个对象类如下*(抽象出属性和行为动作)
package study;
public class Student {
// 学号ID
private int ID;
// 姓名name
private String name;
// 上课状况 status
private String status;
/**
* 构造方法 --初始化对象属性
*
* @param ID 学号
* @param name 姓名
*/
public Student(int ID, String name) {
this.ID = ID;
this.name = name;
}
/**
* 获取学号
*
* @return 返回 学号
*/
public int getID() {
return ID;
}
/**
* 设置学号
* @param iD 要设置的学号
*/
public void setID(int iD) {
ID = iD;
}
/**
* 获取姓名
* @return 返回姓名
*/
public String getName() {
return name;
}
/**
* 设置姓名
* @param name 要设置的姓名
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取上课状态
* @return 返回上课状态
*/
public String getStatus() {
return status;
}
/**
* 设置上课状态
* @param status 要设置的上课状态
*/
public void setStatus(String status) {
this.status = status;
}
/**
* 根据参数message 判断是否在 学习,如果message是"在学习"这个字符串就返回ture 意味着正在学习
* 其他情况下那就意味这没在学习 返回false
* @param message
* @return boolean
*/
public boolean doing(String message){
//如果这名同学在学习,那符合课堂纪律 返回ture
if("在学习".equals(message)){
return true;
}else {
//如果没学习,那违反了课堂纪律 返回 false
return false;
}
}
}
此外,在这里在解释一下构造方法,每一个对象都有自己的构造方法,默认的构造方法是无参数的,构造方法就是与类同名的那个方法,它的作用就是用来初始化成员变量。
package study;
public class Student {
// 学号ID
private int ID;
// 姓名name
private String name;
// 上课状况 status
private String status;
/**
* 构造方法 --初始化对象属性
*
* @param ID 学号
* @param name 姓名
*/
public Student(int ID, String name) {
this.ID = ID;
this.name = name;
}
}
构造方法作用package study;
public class test {
public static void main(String[] args) {
//这就是构造方法的作用
//实例化一个学生 学号是1001 名字张三
Student student =new Student(1001,"张三");
}
}
解释--》new一个对象的时候要用到构造函数,例Student student = new Student();这时调用的是Student的无参数构造方法;Student student = new Student(1001,"张三");这个是
调用Student有参数构造方法,在JAVA中如果不写构造方法的话,会默认加上一个无参数的构造方法,但是如果已经有了一个有参数的构造方法,那么无参数的构造方法就不会默认被
加上.如果Student类中已经有了一个有参数的构造方法,这时再使用 Student student = new Student();来创建对象的时候就会出错,这就是为什么书上要强调写了有参数的构造方
法就最好加一个无参数的构造方法,构造方法是自己写的至于初始化几个成员变量是开发者自己定义的,上面的Student的构造方法只初始化了两个成员变量 学号和姓名,如果
想初始化三个成员变量就定义构造方法为
public Student(int ID, String name,String status) {
this.ID = ID;
this.name = name;
this.status = status;
}
以上读者可以自己尝试。二 封装
细心的小伙伴一定看到了上面的类中多了一些之前没有提到的知识点 ,那就是Getter和Setter,get顾名思义 英语单词是获取的意思,set 是设置/设定的意思
其实对封装的理解我是从Getter/Setter方法开始的,为什么对象的每一个属性要Getter/Setter这样的一组方法呢?原因很简单,这个对象为了保护自己的私有属性,对外公开了一种访问他属性的方法 那就是get 和set (属性是private的,但是get set 方法是public 的)
看看怎么用get 和set 的*(get 和set 用最简单最通俗的方法向我们解释了什么是封装,那就是你要看我就用get 你要设置我就用set)
package study;
public class test {
public static void main(String[] args) {
// 这就是构造方法的作用
// 实例化一个学生 学号是1001 名字张三
Student student = new Student(1001, "张三");
// 调用get方法获得这个学生的学号
int id = student.getID();
// 调用get方法获得这个学生的姓名
String name = student.getName();
System.out.println("我叫" + name + "我的学号是" + id);
// 调用set方法设置这个学生的学习状态
student.setStatus("优");
System.out.println("我的学习状态" + student.getStatus());
}
}
看过上面解释之后大家可能会发现 面向对象是三个特征还是四个特征 ,是因为有些人把抽象和封装一起归类到了封装,我个人是统归为封装的,因为封装也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。可见抽象和封装就一个整体,不可分割。
三 继承
继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
下面我们来一起用一个例子来简单理解一下什么是继承。
现在我们要设计一个类来代表班级干部类Leader ,这个班级干部类除了有普通同学的所有属性和行为动作以外还有一个给同学们的上课表现打分的行为叫scoring,以下是Leader类
package study;
public class Leader extends Student{
/**
* 构造方法
* @param ID 学号
* @param name 姓名
*/
public Leader(int ID, String name) {
super(ID, name);
}
/**
* 班长观察一个同学,然后根据这名同学的表现给这个同学打分
* @param stu 一个同学
* @param message 这个同学正在做的事情
*/
public void scoring(Student stu,String message){
//调用该同学的doing方法获得该同学目前做的事情是否符合课堂纪律
if(stu.doing(message)){
stu.setStatus("优");
}else{
stu.setStatus("差");
}
}
}
测试调用(组长给同学打分)
package study;
public class test {
public static void main(String[] args) {
// 实例化一个学生 学号是1001 名字张三
Student student = new Student(1001, "张三");
// 实例化一个组长 学号1000 名字 牛哥
Leader leader = new Leader(1000, "牛哥");
//组长发现张三这个同学在打游戏于是他给张三打分
//调用组长的打分scoring方法
leader.scoring(student, "在学习");
//调用张三的getStatus方法获取上课状态
String status=student.getStatus();
//打印出来看看
System.out.println(status);//打印结果优
}
}
以上就是简单的一个继承,组长Leader继承了学生Student,目的在于让初级的小伙伴能从简单通俗的例子中感受继承。
总之类和类之间如果想使用继承,那么在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。比如上面的组长属于学生。
四 多态
多态-->书上一般都是这么定义多态的,"可以将子类对象的引用赋给超类类型的变量,因为子类对象是超类的对象”,这句话乍一看很不好理解,但要结合着代码多看几遍,不要怕看不懂,一遍不行,再看一遍,慢慢就会理解的,其实多态就是一句话父类型的引用可以指向子类型的对象
比如上面的
// 实例化一个组长 学号1000 名字 牛哥
Leader leader = new Leader(1000, "牛哥");
可以这样定义
// 实例化一个组长 学号1000 名字 牛哥
Student leader = new Leader(1000, "牛哥");
如果上面的测试中Leader实例化直接改成Student leader = new Leader(1000, "牛哥");测试类编译错误
其实原因就是因为我们在前面定义的父类Student类中没有定义scoring这个方法,所以请注意当使用多态方式调用方法时,
首先检查父类中是否有该方法,如果没有,则编译错误
如果有,再去调用子类的该同名方法
所以在父类Student中定义一个scoring方法
public void scoring(Student stu,String message){
System.out.println("我是Student类");
}
子类scoring方法
/**
* 班长观察一个同学,然后根据这名同学的表现给这个同学打分
* @param stu 一个同学
* @param message 这个同学正在做的事情
*/
public void scoring(Student stu,String message){
System.out.println("我是Leader类");
//调用该同学的doing方法获得该同学目前做的事情是否符合课堂纪律
if(stu.doing(message)){
stu.setStatus("优");
}else{
stu.setStatus("差");
}
}
这个时候再执行测试类
package study;
public class test {
public static void main(String[] args) {
// 实例化一个学生 学号是1001 名字张三
Student student = new Student(1001, "张三");
// 实例化一个组长 学号1000 名字 牛哥
Student leader = new Leader(1000, "牛哥");
//组长发现张三这个同学在打游戏于是他给张三打分
//调用组长的打分scoring方法
leader.scoring(student, "在学习");
//调用张三的getStatus方法获取上课状态
String status=student.getStatus();
//打印出来看看
System.out.println(status);//打印结果
}
}
看控制台输出结果
控制台的输出结果向我们证明了·当使用多态方式调用方法时·如果有,就调用子类的该同名方法
以上就是对面向对象入门级别的解析,希望会对有困扰的小伙伴有所帮助