跳到内容

Clipper 教程:开源 Clipper(s)/面向对象编程指南

来自维基教科书,开放世界中的开放书籍

面向对象编程

[编辑 | 编辑源代码]

Clipper 对 OOP(面向对象编程,从现在开始我们称之为它的昵称)的支持非常有限。它的继任者 CA-Visual Objects 在这方面要先进得多。然而,Visual Objects 从未取得过巨大成功,第三方生产商为 Clipper 提供了 OOP 库,其中最著名的是 Class(y)、TopClass、Fivewin 和 Clip4Win。

从安全距离看面向对象编程

[编辑 | 编辑源代码]

假设我们正在处理给定点的笛卡尔坐标的距离函数 (http://mathinsight.org/cartesian_coordinates)。我们将应用的公式是

分别用于实数线、欧几里得平面和欧几里得空间上的(欧几里得)距离。

在过程式编程中,我们的函数看起来像这样

? distance1d(4,-3)
? distance2d(2,-3,-1,-2)
? distance3d(1,1,1,4,4,4)

        FUNCTION distance1d( x1, x2 )
           RETURN sqrt((x2-x1)^2)

        FUNCTION distance2d( x1,y1,x2,y2 )
           RETURN sqrt((x2-x1)^2+(y2-y1)^2)

        FUNCTION distance3d( x1,y1,z1,x2,y2,z2 )
           RETURN sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)

我们定义了三个函数,具有不同的名称,它们以坐标作为参数。但这样做,我们需要为三维空间中的距离传递六个参数。

如果我们使用面向对象编程来做,我们可能会得到这样的东西

#include "hbclass.ch"

   CREATE CLASS Point1D

   VAR Abscissa    // the abscissa of our point

METHOD New( Abscissa )    // Constructor

METHOD Distance( Point )

   ENDCLASS

   CREATE CLASS Point2D INHERIT Point1D

   VAR Ordinate    // the ordinate of our point

METHOD New( Abscissa, Ordinate )    // Constructor

METHOD Distance( Point )

   ENDCLASS

   CREATE CLASS Point3D INHERIT Point2D

   VAR Zcoord    // the Z-coordinate of our point

METHOD New( Zcoord )    // Constructor

METHOD Distance( Point )

   ENDCLASS

&& Constructors Zone
METHOD New( Abscissa ) CLASS Point1D

   ::Abscissa := Abscissa

   RETURN Self

METHOD New( Abscissa, Ordinate ) CLASS Point2D

   ::Abscissa := Abscissa
   ::Ordinate := Ordinate

   RETURN Self

METHOD New( Abscissa, Ordinate, Zcoord ) CLASS Point3D

   ::Abscissa := Abscissa
   ::Ordinate := Ordinate
   ::Zcoord := Zcoord

   RETURN Self

&&Distances Methods

METHOD Distance( Point ) CLASS Point1D

   RETURN Sqrt( ( Self:Abscissa - Point:Abscissa ) ^ 2 )

METHOD Distance( Point ) CLASS Point2D

   RETURN Sqrt( ( Self:Abscissa - Point:Abscissa ) ^ 2 + ( Self:Ordinate - Point:Ordinate ) ^ 2 )

METHOD Distance( Point ) CLASS Point3D

   RETURN Sqrt( ( Self:Abscissa - Point:Abscissa ) ^ 2 + ( Self:Ordinate - Point:Ordinate ) ^ 2 + ( Self:Zcoord - Point:Zcoord ) ^ 2 )

PROCEDURE Main()

   FirstPoint := Point1D():New( 3 )
   SecondPoint := Point1D():New( - 3 )
   ? FirstPoint:Abscissa
   ? FirstPoint:Distance( SecondPoint )
   ThirdPoint := Point2D():New( 2, - 3 )
   FourthPoint := Point2D():New( - 1, - 2 )
   ? ThirdPoint:Distance( FourthPoint )
   FifthPoint := Point3D():New( 1, 1, 1 )
   SixthPoint := Point3D():New( 4, 4, 4 )
   ? FifthPoint:Distance( SixthPoint )

   RETURN

在这里,我们定义了三个,它们的构造函数,以及每个类的distance方法,并展示了如何使用它们。这也是继承如何工作的简单示例。其他概念是封装信息隐藏数据隐藏)、抽象多态性重载覆盖方法。继承在关键概念:重用中起着核心作用。如果一个类恰好是所需的,那么它可以在软件项目中重用;或者,如果它不是完全需要的,可以通过定义一个子类来扩展它。就像数据库的设计一样,面向对象类的设计也是一门艺术,有其原则,例如参见http://www.oodesign.com/http://www.codeproject.com/articles/567768/object-oriented-design-principles以及有关 UML 的页面,如http://www.uml-diagrams.org/uml-object-oriented-concepts.html

首先要注意的是,我们从包含clipper 头文件hbclass.ch开始,这是 Class 命令的头文件。

对对象变量和方法的访问是通过冒号运算符完成的。前缀双冒号指的是具有更大范围的变量(例如传递给方法的变量)。

在上面的代码中,我们定义了三个类,每个类都实现了一个 Point。例如,Point2D 被定义为一个扩展 Point1D 的类,即概念的泛化。为每个类提供了一个 Distance 方法。

像这样的行

  ? FifthPoint:Distance( SixthPoint )

包含输出命令?,对一个对象的引用(在本例中为FifthPoint),对 Distance 方法:Distance的调用,并将另一个点传递给它( SixthPoint )

也可以编写一个接受两个 Point 类参数的 Distance 函数,看起来像这样

FUNCTION Distance ( Point1, Point2 )
   RETURN Sqrt( ( Point1:Abscissa - Point2:Abscissa ) ^ 2 + ( Point1:Ordinate - Point2:Ordinate ) ^ 2 + ( Point1:Zcoord - Point2:Zcoord ) ^ 2 )

   ? Distance( FifthPoint, SixthPoint )

然而,这不是面向对象编程,因为我们可以在非面向对象语言(如 Pascal 或 C)中使用相同的函数,并传递给它两个名为 Point1 和 Point2 的structrecord(Pascal 称之为)。

重要的是,对象内部的一些数据(由该对象的实际程序员设置)不能被对象用户更改。举一个现实生活中的例子,我们可以考虑汽车发动机。对象的提供者设置了气缸的数量,我们没有太多机会改变:我们必须把它视为一个常数。自然地,关于发动机有很多有趣的公式供工程师使用(一些可以在http://www.thecartech.com/subjects/engine/engine_formulas.htm上看到)。例如,计算发动机容积效率的公式,给定进入气缸的空气量和气缸扫过的体积。这就是数据隐藏的重要性:没有人需要知道这些信息才能让他的汽车行驶。此外,当有人设计发动机时,他们可能不希望用户通过操作发动机来更改容积效率。在面向对象编程中,使用可见性修饰符访问修饰符可以获得相同的效果。

   [CREATE] CLASS <cClassName> [ FROM | INHERIT <cSuperClass1> [, ... ,<cSuperClassN>] ]
             [ MODULE FRIENDLY ] [ STATIC ] [ FUNCTION <cFuncName> ]

   [HIDDEN:]
      [ CLASSDATA | CLASSVAR  | CLASS VAR <DataName1>]
      [ DATA | VAR  <DataName1> [,<DataNameN>] [ AS <type> ] [ INIT <uValue> ]
             [[EXPORTED | VISIBLE] | [PROTECTED] | [HIDDEN]] [READONLY | RO] ]
      ...
      [ METHOD <MethodName>( [<params,...>] ) [CONSTRUCTOR] ]
      [ METHOD <MethodName>( [<params,...>] ) INLINE <Code,...> ]
      [ METHOD <MethodName>( [<params,...>] ) BLOCK  <CodeBlock> ]
      [ METHOD <MethodName>( [<params,...>] ) EXTERN <funcName>([<args,...>]) ]
      [ METHOD <MethodName>( [<params,...>] ) SETGET ]
      [ METHOD <MethodName>( [<params,...>] ) VIRTUAL ]
      [ METHOD <MethodName>( [<params,...>] ) OPERATOR <op> ]
      [ ERROR HANDLER <MethodName>( [<params,...>] ) ]
      [ ON ERROR <MethodName>( [<params,...>] ) ]
      ...
   [PROTECTED:]
      ...
   [VISIBLE:]
   [EXPORTED:]
      ...

   [FRIEND CLASS <ClassName,...>]
   [FRIEND FUNCTION <FuncName,...>]

   [SYNC METHOD <cSyncMethod>]

   ENDCLASS [ LOCK | LOCKED ]

另一个例子

[编辑 | 编辑源代码]

w:Harbour (软件) 中逐字复制

 #include "hbclass.ch"

 PROCEDURE Main()

    LOCAL oPerson

    CLS

    oPerson := Person():New( "Dave" )

    oPerson:Eyes := "Invalid"

    oPerson:Eyes := "Blue"

    Alert( oPerson:Describe() )

    RETURN

 CREATE CLASS Person

    VAR Name INIT ""

    METHOD New( cName )
    METHOD Describe()

    ACCESS Eyes INLINE ::pvtEyes
    ASSIGN Eyes( x ) INLINE iif( HB_ISSTRING( x ) .AND. x $ "Blue,Brown,Green", ::pvtEyes := x, Alert( "Invalid value" ) )

    PROTECTED:

    VAR pvtEyes

 ENDCLASS

 // Sample of normal Method definition
 METHOD New( cName ) CLASS Person

    ::Name := cName

    RETURN Self

 METHOD Describe() CLASS Person

    LOCAL cDescription

    IF Empty( ::Name )
       cDescription := "I have no name yet."
    ELSE
       cDescription := "My name is: " + ::Name + ";"
    ENDIF

    IF ! Empty( ::Eyes )
       cDescription += "my eyes' color is: " + ::Eyes
    ENDIF

    RETURN cDescription
华夏公益教科书