面向对象的个人总结

天僖 2017-07-02 04:53:32
程序猿这一行学无止境,我近期抽出一点时间,梳理一下java基础部分,一是写给自己,也乐意分享给大家.今天是对面向对象的总结.

面向对象是编程是一种编写程序的方法,旨在提高开发程序的效率,提高程序的可维护性.熟练掌握面向对象的方法来编写程序,是十分必要的.

面型对象的三大特点:

封 装(面向对象特征之一):是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:将变化隔离;便于使用;提高重用性;安全性。
封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。

继 承(面向对象特征之一)
好处:
1:提高了代码的复用性。
2:让类与类之间产生了关系,提供了另一个特征多态的前提。

父类的由来:其实是由多个类不断向上抽取共性内容而来的。
java中对于继承,java只支持单继承。java虽然不直接支持多继承,但是保留了这种多继承机制,进行改良。

单继承:一个类只能有一个父类。
多继承:一个类可以有多个父类。

为什么不支持多继承呢?
因为当一个类同时继承两个父类时,两个父类中有相同的功能,那么子类对象调用该功能时,运行哪一个呢?因为父类中的方法中存在方法体。
但是java支持多重继承。A继承B B继承C C继承D。
多重继承的出现,就有了继承体系。体系中的顶层父类是通过不断向上抽取而来的。它里面定义的该体系最基本最共性内容的功能。
所以,一个体系要想被使用,直接查阅该系统中的父类的功能即可知道该体系的基本用法。那么想要使用一个体系时,需要建立对象。建议建立最子类对象,因为最子类不仅可以使用父类中的功能。还可以使用子类特有的一些功能。

简单说:对于一个继承体系的使用,查阅顶层父类中的内容,创建最底层子类的对象。

子父类出现后,类中的成员都有了哪些特点:
1:成员变量。
当子父类中出现一样的属性时,子类类型的对象,调用该属性,值是子类的属性值。
如果想要调用父类中的属性值,需要使用一个关键字:super
This:代表是本类类型的对象引用。
Super:代表是子类所属的父类中的内存空间引用。
注意:子父类中通常是不会出现同名成员变量的,因为父类中只要定义了,子类就不用在定义了,直接继承过来用就可以了。
2:成员函数。
当子父类中出现了一模一样的方法时,建立子类对象会运行子类中的方法。好像父类中的方法被覆盖掉一样。所以这种情况,是函数的另一个特性:覆盖(复写,重写)
什么时候使用覆盖呢?当一个类的功能内容需要修改时,可以通过覆盖来实现。
3:构造函数。
发现子类构造函数运行时,先运行了父类的构造函数。为什么呢?
原因:子类的所有构造函数中的第一行,其实都有一条隐身的语句super();
super(): 表示父类的构造函数,并会调用于参数相对应的父类中的构造函数。而super():是在调用父类中空参数的构造函数。
为什么子类对象初始化时,都需要调用父类中的函数?(为什么要在子类构造函数的第一行加入这个super()?)
因为子类继承父类,会继承到父类中的数据,所以必须要看父类是如何对自己的数据进行初始化的。所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。

注意:子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();
如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数。
如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。

多 态(面向对象特征之一):函数本身就具备多态性,某一种事物有不同的具体的体现。

体现:父类引用或者接口的引用指向了自己的子类对象。//Animal a = new Cat();
多态的好处:提高了程序的扩展性。
多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。(前期不能使用后期产生的功能,即访问的局限性)
多态的前提:
1:必须要有关系,比如继承、或者实现。
2:通常会有覆盖操作。

多态的出现思想上也做着变化:以前是创建对象并指挥对象做事情。有了多态以后,我们可以找到对象的共性类型,直接操作共性类型做事情即可,这样可以指挥一批对象做事情,即通过操作父类或接口实现。

多态在子父类中的成员上的体现的特点:
1,成员变量:在多态中,子父类成员变量同名。
在编译时期:参考的是引用型变量所属的类中是否有调用的成员。(编译时不产生对象,只检查语法错误)
运行时期:也是参考引用型变量所属的类中是否有调用的成员。
简单一句话:无论编译和运行,成员变量参考的都是引用变量所属的类中的成员变量。
再说的更容易记忆一些:成员变量 --- 编译运行都看 = 左边。
2,成员函数。
编译时期:参考引用型变量所属的类中是否有调用的方法。
运行事情:参考的是对象所属的类中是否有调用的方法。
为什么是这样的呢?因为在子父类中,对于一模一样的成员函数,有一个特性:覆盖。
简单一句:成员函数,编译看引用型变量所属的类,运行看对象所属的类。
更简单:成员函数 --- 编译看 = 左边,运行看 = 右边。
3,静态函数。
编译时期:参考的是引用型变量所属的类中是否有调用的成员。
运行时期:也是参考引用型变量所属的类中是否有调用的成员。
为什么是这样的呢?因为静态方法,其实不所属于对象,而是所属于该方法所在的类。
调用静态的方法引用是哪个类的引用调用的就是哪个类中的静态方法。
简单说:静态函数 --- 编译运行都看 = 左边。



三大特点总结完,我写一个小案例,来更通俗易懂的介绍面向对象的一些特点.

我们首先思考一下,如果让你写一个计算两个数加减乘除的小程序,一个初学者可能会怎么写?
我这里有一段代码:



所以以上的的程序尽管能实现基本的功能,但还需要改进,一段代码实现想要的功能仅仅只是开始远非结束!

这里是稍微改进后的代码
package com.itjava;

import java.util.Scanner;

public class MyCount1 {

public static void main(String[] args) {

try {
// 创建sc对象用于输入数据
Scanner sc = new Scanner(System.in);

// 分别输入两个数字
System.out.println("请输入数字a");
String strNumberA = sc.nextLine();

System.out.println("请输入数字b");
String strNumberB = sc.nextLine();
// 选择一个运算符
System.out.println("请选择运算符 (+.-.*./):");
String strOperate = sc.nextLine();

// 初始化一个字符串答案
String strResult = "";

switch (strOperate) {
case "+":
strResult = Double.toString(Double.parseDouble(strNumberA) + Double.parseDouble(strNumberB));
break;
case "-":
strResult = Double.toString(Double.parseDouble(strNumberA) - Double.parseDouble(strNumberB));
break;
case "*":
strResult = Double.toString(Double.parseDouble(strNumberA) * Double.parseDouble(strNumberB));
break;
case "/":
if (strNumberB != "0") {
strResult = Double.toString(Double.parseDouble(strNumberA) / Double.parseDouble(strNumberB));
} else {
System.out.println("除数不能为0");
}
break;
}
System.out.println("结果是:" + strResult);
} catch (NumberFormatException e) {
System.out.println("您输入的数字或运算符号有误" + e.getMessage());
}
}
}

变量命名尽量做到见名知意,方便自己,也方便别人阅读.
用swicth语句,避免了计算机的不必要的判断,提高效率.
最后用捕获异常的方式,将用户输入的不正确内容显示出来.

是不是清晰多了?

不过这段代码还没有体现出面向对象的优越性,我们需要用封装.继承.多态,来降低程序的耦合性,提高程序的可维护性.复用性和可拓展性.

下面我们试试把这段代码封装成一个方法

package com.itjava;

import java.util.Scanner;

public class MyCount2 {

public static void main(String[] args) {
// 除0会得到Infinity,表示无限大
try {
// 创建sc对象用于输入数据
Scanner sc = new Scanner(System.in);

// 分别输入两个数字
System.out.println("请输入数字a");
String strNumberA = sc.nextLine();

System.out.println("请输入数字b");
String strNumberB = sc.nextLine();
// 选择一个运算符
System.out.println("请选择运算符 (+.-.*./):");
String strOperate = sc.nextLine();

String strResult = getResult(strNumberA, strNumberB, strOperate);

System.out.println("符号" + strOperate + "的运算结果为:" + strResult);

} catch (NumberFormatException e) {
// 捕获异常并提示
System.out.println("您输入的数字或符号有误" + e.getLocalizedMessage());
}
}

public static String getResult(String strNumberA, String strNumberB, String strOperate) {

// 初始化一个字符串答案
String strResult = "";

switch (strOperate) {
case "+":
strResult = Double.toString(Double.parseDouble(strNumberA) + Double.parseDouble(strNumberB));
break;
case "-":
strResult = Double.toString(Double.parseDouble(strNumberA) - Double.parseDouble(strNumberB));
break;
case "*":
strResult = Double.toString(Double.parseDouble(strNumberA) * Double.parseDouble(strNumberB));
break;
case "/":
strResult = Double.toString(Double.parseDouble(strNumberA) / Double.parseDouble(strNumberB));
break;
}
return strResult;
}
}

这里直接调用了计算方法,提高了程序的复用性,不过程序的可维护性和可拓展性还不够,想一想如果我们要添加其他计算方法该怎么办?要在这段代码里加内容吧?现在这段代码还算少,如果程序够多那么添加其他方法或者修改原来的内容就很麻烦,容易出错,
这里就需要创建父类来规定子类的特性,通过添加子类来添加其他计算方法.

来看下面的内容

package com.itjava1;

public abstract class Operation {
// 成员属性
private double NumberA;
private double NumberB;
private String strResult;

// 定义一个获得结果的抽象方法,让加减乘除等子类实现这个方法
public abstract String getResult(double NumberA, double NumberB);

// 无参构造
public Operation() {
super();
// TODO Auto-generated constructor stub
}

// 含参构造
public Operation(double NumberA, double NumberB, String strResult) {
super();
this.NumberA = NumberA;
this.NumberB = NumberB;
this.strResult = strResult;
}

public double getNumberA() {
return NumberA;
}

public void setNumberA(double NumberA) {
this.NumberA = NumberA;
}

public double getNumberB() {
return NumberB;
}

public void setStrNumberB(double NumberB) {
this.NumberB = NumberB;
}

public String getStrResult() {
return strResult;
}

public void setStrResult(String strResult) {
this.strResult = strResult;
}
}

定义一个运算父类,再创建一个抽象方法规定子类的实现

package com.itjava1;

public class Addition extends Operation {

@Override
public String getResult(double NumberA, double NumberB) {
String strResult = Double.toString(NumberA + NumberB);
return strResult;
}
}
//加法

package com.itjava1;

public class Division extends Operation {

@Override
public String getResult(double NumberA, double NumberB) {
String strResult = Double.toString(NumberA-NumberB) ;
return strResult;
}
}
//减法

package com.itjava1;

public class Multiplication extends Operation {

@Override
public String getResult(double NumberA, double NumberB) {
String strResult = Double.toString(NumberA * NumberB);
return strResult;
}
}
//乘法

package com.itjava1;

public class Subtraction extends Operation {

@Override
public String getResult(double NumberA, double NumberB) {
String strResult = Double.toString(NumberA/NumberB) ;
return strResult;
}
}
//除法

package com.itjava1;

public class OperationFactory {

public static Operation createOperate(String operate) {
//通过加减乘除符号,获取加减乘除四个类的对象
Operation oper = null;
switch (operate) {
case "+":
oper = new Addition();
break;
case "-":
oper = new Division();
break;
case "*":
oper = new Multiplication();
break;
case "/":
oper = new Subtraction();
break;
}
return oper;
}
}
//定义一个工厂类,用来获取子类的对象oper

package com.itjava1;

import java.util.Scanner;

public class Test {
public static void main(String[] args) {
// 客户端代码

// 创建sc对象用于输入数据
Scanner sc = new Scanner(System.in);

// 分别输入两个数字
System.out.println("请输入数字A");
String strNumberA = sc.nextLine();

System.out.println("请输入数字B");
String strNumberB = sc.nextLine();
// 选择一个运算符
System.out.println("请选择运算符 (+.-.*./):");
String strOperate = sc.nextLine();

double NumberA = Double.parseDouble(strNumberA);
double NumberB = Double.parseDouble(strNumberB);

Operation oper;
// 获得子类Addition的对象(多态)
oper = OperationFactory.createOperate(strOperate);

String result = oper.getResult(NumberA, NumberB);

System.out.println(result);
}
}

//最后通过加减乘除的符号,获取想要的子类对象,并调用子类实现的方法,这个是简易的工厂模式,这一系列的修改,大大增加了代码的可维护性.可拓展性和可复用性.

...全文
1095 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Immer_L6 2017-07-22
  • 打赏
  • 举报
回复
已抄收,谢谢分享
pengjianwu1994 2017-07-21
  • 打赏
  • 举报
回复
非常有帮助,感谢提供
Jcon_ 2017-07-20
  • 打赏
  • 举报
回复
总结得很不错。
自由自在_Yu 2017-07-20
  • 打赏
  • 举报
回复
写博客呗,这样大家看着方便
自由自在_Yu 2017-07-20
  • 打赏
  • 举报
回复
Slopr 2017-07-20
  • 打赏
  • 举报
回复
最近在学JavaSE,感谢楼主的总结。
窝 窝 2017-07-19
  • 打赏
  • 举报
回复
LanCoffee117 2017-07-18
  • 打赏
  • 举报
回复
看了一些感觉非常有帮助!!
best_jangbi 2017-07-18
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
se还没有学完,等学完se再来拜读,留爪
tzy0526 2017-07-11
  • 打赏
  • 举报
回复
Java_CcMan 2017-07-07
  • 打赏
  • 举报
回复
qq_37171619 2017-07-04
  • 打赏
  • 举报
回复
心向远方 2017-07-04
  • 打赏
  • 举报
回复
我还以为是面向对象,原来是面向对象啊
暴雨中漫步 2017-07-03
  • 打赏
  • 举报
回复
李德胜1995 2017-07-02
  • 打赏
  • 举报
回复

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧