面向对象程序设计课程总结

课程学习过程总结

开始进行编程时仍旧保持了之前学习C的习惯,用面向过程的思维方式进行思考,大量的使用了静态变量static定义的方法和属性但随着课程的深入面向过程的有些不便方面就展现出来了,对于复杂的程序设计问题的解决不便于模块化处理

 

 

水文数据处理

 

 

 

 

 

使用面向对象设计时只需要考虑问题策涉及哪些对象,对象具有哪些属性和功能

最后对于这些功能属性进行调用即可。

挡你开始习惯使用面向对象进行思考时新的问题就来了,如何去进行对象类的设计,老师开始时会在每次作业发布时附带作业指导书,会对于类的设计给予一定的指导。当你需要自己设计一个完整的程序时问题就出现了关于最后一次PTA作业我是这样设计的

题目如下:

 

 

是一个表达式计算的题目有两个要求一是合法表达式,二是对于正确合法的表达式进行结果输出。

为了实现程序首先设计一个检测输入表达式是否非法的判断类

 

public class TextData

 

根据测试点一一进行方法设计

 

 

之后需要进行表达是的计算设计一个计算类

public class toDeal

计算的核心在于算法

根据了解有人已经设计出来了对于该种表达式计算的算法(波兰表达式),我只需要进行学习即可。

 

关于Java与C

 

从开始课程到现在一共进行了九次PTA作业,在接触面向对象程序设计之前学习的是面向过程的的语言两编程语言C,对于程序的基本设计的相关的知识,例如:数据类型表达式求值以及操作符的优先级,选择相关的if语句,数学函数字符以及字符串,循环,数组使用有些一些基本的了解。但毕竟是一门全新者之间还是有很多的不同,

 

java语言和c语言的区别:                                      1

 

un 公司推出的Java 是面向对象程序设计语言,其适用于Internet 应用的开发,称为网络时代重要的语言之一。Java 可以用认为是C 的衍生语言,与C 在大量元以内成分保持相同,例如此法结构、表达式语句、运算符等与C基本一致:但Java更简洁,没有C中冗余以及容易引起异常的功能成分,并且增加了多线程、异常处理、网络编程等方面的支持功能。本文从多角度对JavaC进行对比分析,为CJava语言的学习提高一些借鉴。

 

 

 

调法结构

 

       CJava的词法结构很相似,针对程序中的空白符、标识符、注释、常量、运算符、分隔符和关键字等进行详细对比分析。

 

1.1、空白符和注释

 

        空白符包括空格、制表符和换行符。

 

C中存在两种注释:

 

1)注释语句以/*开头,以*/结束。

 

2)注释可以用//开始,延伸到下一个行终结符。

 

Java包含了C的两种注释和空白符。

 

 

 

1.2、标识符

 

C的标识符集合是Java 的标识符集合的一个子集。C中标识符由大小写拉丁字符、数字和下划线组成的,且不能以数字开头,不能与关键字相同;

 

Java的标识符由大小写拉丁字符、数字、下划线以及$组成,也不能以数字开头;

 

 

 

1.3、关键字和保留标识符

 

         关键字是语言的特殊符号,CJava的关键字较相似。

 

有些关键字Java中独有的,如下图所示:

 

abstract
assert
boolean
byte
catch
class
extends
Final
finally
implements
import
instranceof
interface
native
New
package
private
protected
public
strictfp
super
synchronized
this
throw
throws
transient
try
 
有些关键字在C中使用而Java未使用,下表所示为C中独有的关键字。

 

Auto _bool _Complex extern _Imaginary inline register
restrict signed sizeof struct typedef union Usigned

 


1.4、常量

 

          常量包括4中类型:整形、浮点型、字符型和字符串型。对于常量,CJava存在细微的差别。

 

1) C中整型常数中只有无符号整型常数比Java的整型常数大,Java中没有后缀long long型和unsigned;

 

2) C Java 的字符常量和字符串常量很接近,C中有续行机制,即如果字符串太长,一行放不下,则可以在行末加上一个反斜杠,反斜杠和行终结符被忽略,使字符串常量可以写在多行中,并且所有的源行都可以续航。但Java 中,不允许字符串跨越多行。

 

3) C中每个字符串都是由空字符("\0")来结尾,而Java 的字符串中没有如此的终结符。

 

4) C中,"0"还可以表示布尔值假(false)或指针空(NULL),在Java采用保留标识符false NULL

 

 

 

1.5、运算符和分隔符

 

      Java 中大多数运算符和分隔符与C是兼容的,C中提供的运算符几乎完全适合于Java语言。两者的细微差别是:

 

1C中独有间接成员运算符(->)、取值运算符(*)、地址运算符(&)、逗号运算符(,);

 

2Java 不提供指针运算符,增加了对象操作符 instanceof、字符串运算符+和零填充的右移》等;

 

3)与C不同的是,Java中算数运算符不能用在布尔类型上,逻辑运算符的操作数只能是布尔型而不能是整型,在转换中需要进行特殊处理;

 

4C中利用 sizeof 进行数据分配和释放内存以及获取的数据的个数,但在java中没有此运算符,因为所有的数据类型在所有机器中的大小都是相同的;

 

 

 

数据类型

 

      C中数据类型分为:算书类型、指针类型、数组类型、结构类型、联合类型、枚举类型、函数类型和void类型,以下对上述类型在JavaC的异同以及类型转异换进行比较分析。

 

2.1、算术类型

 

         C中算术类型包括整型和浮点型。C中的整型有字符类型、布尔类型和枚举类型。C中类型大小依赖于C编译器的具体实现;

 

         Java对基本数据类型大小有明确约定,其中char 是一个2字节的无符号整数,用来存储Unicode字符。除char类型外,Java不支持无符号整型,其它整型都是无符号的;

 

并且Cchar类型的用法比Java中灵活。Cchar类型的数组和指针可以用来表示字符串,而Java须使用string类表示。

 

 

 

2.2、结构和联合类型

 

         Java中没有结构类型;在C中声明结构变量时编译器会为其分配内存空间,而在Java中需要用new来分配空间;C中允许不完整初始化以及声明匿名结构(可嵌套),在Java中确实不被允许的;Java中没有与C中对应的联合类型这种语言结构。

 

 

 

2.3、枚举类型

 

          C中,枚举类型声明代表整数常量的符号名称,枚举常量事实上是int 类型;

 

          Java 中,存在枚举类型,关键字enum 声明的枚举变量事实上是java.lang.Enum 的一个子类,可以为其添加属性和方法,虽然其中的枚举常量也是int 类型,但不能用整数初始化,也不能作为整型使用。

 

 

 

2.4void类型

 

          C Java 都支持 void 类型。

 

          C void 可代替函数参数表以及表示函数不带参数,在建立 void * 类型时,void * 类型的变量可以存储一个指向任意类型或函数的指针;

 

          Java 中的 void 仅表示方法没有返回值。

 

 

 

2.5typedef

 

          C typedef 不是预处理指令,而是为某一类型创建另外名字的,并且C允许在一个typedef 中引用另一个 typedef 定义的名字;

 

          Java 中没有与之对应的机制;

 

 

 

2.6、数据类型转换

 

          Java 语言属于强类型语言,对数据类型兼容性要求比C更严格,这保障了他的安全性和健壮性。Java中所有的数值传递,无论是直接还是通过参数传递的都先要进行类型兼容性的检查,任何类型的不匹配的都会产生编译错误。在Java 中,整数类型、浮点数类型和字符类型是彼此兼容的,但和布尔类型是不兼容的,除了布尔型和枚举类型,Java中允许吧任何基本类型转换成别的基本类型;

 

          C中表示真/假的变量一直是由int 类型来表示的。C允许从算术类型转换为布尔类型。Java 不允许在这两种类型之间进行隐式和显式的转换,也不能比较布尔型和算术型。

 

 

 

3、表达式和语句

 

         Java的表达式和语句与C的几近一致,存在一些细微差别:在Java ifwritefor 语句中的条件表达式应该是布尔型,在C中可以是整形;Java 不提供goto语句,goto语句的存在可以改变程序的运行方式,是程序的安全性和稳定性降低,Java利用代表号的break 语句和continue语句实现转移功能;表达式语句在Java中比C有更多的限制,Java中只允许复制、函数调用、自增减、new 表达式等出现在表达式语句中。

 

 

 

4、函数

 

1)对于变量和函数,C需要实现声明和定义,而Java中只有定义,没有声明;

 

2)由于C不是面向对象的,所以C中所有全局变量和函数本质上对Java而言都是静态的。Java是一种面向对象语言,它不允许在类和接口之外声明函数,包括 main 函数和变量。而在C中,常会出现在一个文件中定义大量的全局变量,在其他文件中通过引用声明这些变量来实现共享,但Java不允许有全局变量或函数;

 

3)当C中函数返回值的类型和声明时类型不相符时,函数的返回值会自动转换为这个类型之后再进行函数返回;而在Java中面对次情况时,需要加入强制类型转换;

 

4C中函数调用参数计算的顺序是未定义的,而Java 是从左到右有顺序的;

 

5C中如果变量或函数在别的文件中定义的,必须使用extern 来声明该变量或函数。在单个文件编译的时候它们是不可见,而在链接阶段才可见。Java的编译器没有这种链接阶段,所有需要的文件在编译时必须可见;

 

6CJava程序都从 main 函数开始执行。Cmain 函数一般需要有 argc,argv 两个参数,argc 存在命令行参数个数,argv 存在实际的命令行参数;java main 必须用 stringargs[] 作为方法的参数,它是用来接收运行系统启动Java 应用程序时所用的命令行的参数;

 

7CJava中可以调用 exit 函数来终结程序;C中可利用abort 函数来退出非正常终止的程序,Java 中没有相对应的策略。

 

 

 

5、数组

 

1)数组是同一类型的数据元素的有序序列。Java 程序在编译和运行时严格地检查所有数组的边界,提高了程序的安全性;在C中并没有提供边界检查功能,如此可以提供程序的运行速度;

 

2)在C中,数组一般是在定义时就指定其大小,由编译器分配数组所需的一块连续的内存空间,而且数组中的元素是按顺序存储的;在Java 中,数组定义时不被允许指定数组的大小,同时也不会为其分配内存空间,需要用new 运算符显示创建,或者通过初始化方法隐式创建,数组所占用的空间由Java的来及收集器自动地回收;

 

3C 中如果部分初始化数组,未促使花的元素则被设置为0Java并不直接支持多维数组,但可以创建数组的数组,用这种方法可以实现多维数组;

 

4)值得注意的是,在C中数组实际得到的是它的指针,而在Java中得到的是引用,不是指针。在Java中程序只能通过下标运算符和访问数组元素,不能像C中的指针那样通过整数加减运算来访问元素;

 

5C允许数组的牵引类型可以为long型,而Java 的要求是 int 型。

 

 

 

6、预处理器及头文件的比较

 

       Java没有预处理器,也没有头文件;C中预处理器只是接收一些文本并将其转换成为其他文本,编译器对预处理的源程序进行编译,在C中通常用头文件来声明原型以及全局变量、库函数等。

 

 

 

关于这两种语言最本质的区别还是面向对象与面向过程的区别:

 

面向=对象有三个基本特征:封装、继承、多态

 

 

 

 

 

封装

 

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

 

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

 

继承

 

面向对象编程语言的一个主要功能就是继承。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

 

通过继承创建的新类称为子类派生类

 

被继承的类称为基类父类超类

 

继承的过程,就是从一般到特殊的过程。

 

要实现继承,可以通过继承Inheritance)和组合Composition)来实现。

 

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

 

 

 

继承概念的实现方式有三类:实现继承、接口继承和可视继承。

 

Ø         实现继承是指使用基类的属性和方法而无需额外编码的能力;

 

Ø         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

 

Ø         可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。

 

在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是属于关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。

 

抽象类仅定义将由子类创建的一般属性和方法,创建抽象类时,请使用关键字 Interface 而不是 Class

 

OO开发范式大致为:划分对象抽象类将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

 

 

 

多态

 

多态性(polymorphism)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

 

实现多态,有二种方式,覆盖,重载。

 

覆盖,是指子类重新定义父类的虚函数的做法。

 

重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

 

其实,重载的概念并不属于面向对象编程,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_funcstr_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!真正和多态相关的是覆盖。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对象也无关!引用一句Bruce Eckel的话:不要犯傻,如果它不是晚邦定,它就不是多态。

 

那么,多态的作用是什么呢?

 

我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用家谱中任一类的实例的某一属性时的正确调用。

 

 

 

概念理解

 

泛化(Generalization

 

 

 

 

 

 

 

在上图中,空心的三角表示继承关系(类继承),在UML的术语中,这种关系被称为泛化(Generalization)。Person()是基类,Teacher(教师)Student(学生)Guest(来宾)是子类。

若在逻辑上BA一种,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性。

例如,教师是人,Teacher Person一种a kind of )。那么类Teacher可以从类Person派生(继承)。

如果A是基类,BA的派生类,那么B将继承A的数据和函数。

如果类A和类B毫不相关,不可以为了使B的功能更多些而让B继承A的功能和属性。

若在逻辑上BA一种a kind of ),则允许B继承A的功能和属性。

 

聚合(组合)

 

 

若在逻辑上AB一部分a part of),则不允许BA派生,而是要用A和其它东西组合出B

例如,眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,所以类Head应该由类EyeNoseMouthEar组合而成,不是派生(继承)而成。

 

聚合的类型分为无、共享(聚合)、复合(组合)三类。

 

聚合(aggregation

 

 

上面图中,有一个菱形(空心)表示聚合(aggregation)(聚合类型为共享),聚合的意义表示has-a关系。聚合是一种相对松散的关系,聚合类B不需要对被聚合的类A负责。

 

组合(composition

 

 

这幅图与上面的唯一区别是菱形为实心的,它代表了一种更为坚固的关系——组合(composition)(聚合类型为复合)。组合表示的关系也是has-a,不过在这里,A的生命期受B控制。即A会随着B的创建而创建,随B的消亡而消亡。

 

这里BA的关系只是一种依赖(Dependency)关系,这种关系表明,如果类A被修改,那么类B会受到影响。

二、五种设计原则

"面向对象设计五大原则"和良性依赖原则在应付变化方面的作用。

单一职责原则(Single-Resposibility Principle)"对一个类而言,应该仅有一个引起它变化的原因。"本原则是我们非常熟悉地"高内聚性原则"的引申,但是通过将"职责"极具创意地定义为"变化的原因",使得本原则极具操作性,尽显大师风范。同时,本原则还揭示了内聚性和耦合生,基本途径就是提高内聚性;如果一个类承担的职责过多,那么这些职责就会相互依赖,一个职责的变化可能会影响另一个职责的履行。其实OOD的实质,就是合理地进行类的职责分配。

开放封闭原则(Open-Closed principle)"软件实体应该是可以扩展的,但是不可修改。"本原则紧紧围绕变化展开,变化来临时,如果不必改动软件实体裁的源代码,就能扩充它的行为,那么这个软件实体设计就是满足开放封闭原则的。如果说我们预测到某种变化,或者某种变化发生了,我们应当创建抽象类来隔离以后发生的同类变化。在Java中,这种抽象是指抽象基类或接口;在C++中,这各抽象是指抽象基类或纯抽象基类。当然,没有对所有情况都贴切的模型,我们必须对软件实体应该面对的变化做出选择。

Liskov替换原则(Liskov-Substituion Principle)"子类型必须能够替换掉它们的基类型。"本原则和开放封闭原则关系密切,正是子类型的可替换性,才使得使用基类型模块无需修改就可扩充。Liskov替换原则从基于契约的设计演化而来,契约通过为每个方法声明"先验条件""后验条件";定义子类时,必须遵守这些"先验条件""后验条件"。当前基于契的设计发展势头正劲,对实现"软件工厂""组装生产"梦想是一个有力的支持。

依赖倒置原则(Dependecy-Inversion Principle)"抽象不应依赖于细节,细节应该依赖于抽象。"本原则几乎就是软件设计的正本清源之道。因为人解决问题的思考过程是先抽象后具体,从笼统到细节,所以我们先生产出的势必是抽象程度比较高的实体,而后才是更加细节化的实体。于是,"细节依赖于抽象"就意味着后来的依赖于先前的,这是自然而然的重用之道。而且,抽象的实体代表着笼而统之的认识,人们总是比较容易正确认识它们,而且本身也是不易变的,依赖于它们是安全的。依赖倒置原则适应了人类认识过程的规律,是面向对象设计的标志所在。

接口隔离原则(Interface-Segregation Principle)"多个专用接口优于一个单一的通用接口。"本原则是单一职责原则用于接口设计的自然结果。一个接口应该保证,实现该接口的实例对象可以只呈现为单一的角色;这样,当某个客户程序的要求发生变化,而迫使接口发生改变时,影响到其他客户程序的可能生性小。

良性依赖原则。"不会在实际中造成危害的依赖关系,都是良性依赖。"通过分析不难发现,本原则的核心思想是"务实",很好地揭示了极限编程(Extreme Programming)"简单设计""重构"的理论基础。本原则可以帮助我们抵御"面向对象设计五大原则"以及设计模式的诱惑,以免陷入过度设计(Over-engineering)的尴尬境地,带来不必要的复杂性。

 

测试的理解与实践的重要性

在实验课时我们学习了关于debug的基本使用以及测试代码的编写,好的测试可以有效发现代码所存在的问题,并及时给予解决,对于提升代码质量尤为关键。程序设计是一门设计课需要大量的练习,仅仅停留在理论和书本上是不行的,需要大量的练习,提升自己的实践能力。

对于课堂的收获

提高了解决问题的能力,以及克服困难,耐得住寂寞,勤于思考的优良品质。

 

posted @ 2020-06-06 10:41  7%  阅读(330)  评论(0编辑  收藏  举报