Home >php教程 >php手册 >php之面向对象

php之面向对象

WBOY
WBOYOriginal
2016-06-13 09:37:53753browse

  讲到面向对象 先回顾下以前的编程思路,所谓编程思路就是根据知识本质原理通过逻辑推理程序的过程,编程思路,讲究的是先明确要做的事情是怎么。离开代码的情况下,自己也要能明白这一件事情怎么做。而不是把代码背一遍。跟据要做的事情,去确认各种已知条件,没有条件的要自己创造条件。也就是:知道条件,知道结果,求过程。 在实际程序中 我们往往要做很多的准备工作 去创造满足条件,比如要输出mysql的一段数据我们需要准备分页计算,才知道要从哪里输出到哪里,往往一个程序中。一个功能,一个流程,不能满足整个功能的需要。需要好几个流程配合才能完成,比如,当网页打开的时候做什么,当表单提交的时候做什么,没有提交做什么,数据库连不上的时候做什么连上的时候做什么。 当没有表单提交来的时候($_POST 为空的时候),我们就显示表单。有数据提交来的时候,我们就连接数据库,整理SQL语句,写入数据库。然后给用户一个提示性的页面。总结下来 ,我们整个程序在思考的时候 就会这么想 程序运行到这里的时候程序需要做什么,怎么做,才能满足下一个流程的需求,这几个流程组合起来,才能满足整个功能的需求,这种思考方式,我们称之为面向过程,面向过程 总结下来 思考模式有一个共通的特点:什么时候做什么,怎么做,每一个流程 每一步。这就是面向过程。

  其实在我们写代码的时候 九成以上都是面向过程,而相对的面向对象 只是一种思考方式的名字,很多的时候我们也会使用面向对象的方式思考 只是自己不知道罢了,以下代码是一个简单的例子:

<span $file</span> = "test.txt"<span ;//指定打开的文件
</span><span $fp</span> = <span fopen</span>(<span $file</span>, "r"<span );//打开文件
</span><span $data</span> = <span fread</span>(<span $fp</span>, 1024<span );//读取数据赋值
</span><span fclose</span>(<span $fp</span><span );//关闭文件
</span><span echo</span> <span $data</span>;//输出

一段代码对应了一个过程

  我们在读取数据库的时候现在很多人应该是这么思考的了。//连接数据库//查询数据库//显示结果,

  如果是身份验证。还多一个流程。//连接数据库//查询数据库//对比用户名和密码//显示结果。这个注释其实就是思路的描述,当我们写代码熟练到一定程度的时候,就已经没必要去一行一行的想了。往往想到一个流程,就是几行代码,但是,代码实际的功能,必须和思考的过程吻合。

还是上面的一段代码

<span $fp</span> = <span fopen</span>(<span $file</span>, "r"<span );
</span><span $data</span> = <span fread</span>(<span $fp</span>, 1024<span );
</span><span fclose</span>(<span $fp</span><span );
</span><span //整体注释就是:</span><span 读取&ldquo;文件&rdquo;的&ldquo;内容&rdquo;<br /><br /></span> //如果我换成另一个同样功能函数呢
  $file = "test.txt";
  $data = file_get_contents($file); 
<span  </span>

这个写法,更符合我们刚才的描述:读取文件内容。在这里,$file 我们思考的时候,把它看成了一个文件。

  又比如 对于图形处理过程我们可以理解为:创建一张图像,往图像里写字,往图像里画线,输出图像,把这个资源量看成这张图像本身。

  所谓的面向对象就是思考模式的描述,在这种思考模式下我们把要处理的各个东西想象成一个个实体,读取文件  处理数据  写入文件  。。创建图像 在图像上绘画  在图像上写字  输出图像 虽然从代码本质上来解读的话它们还是一个个的各种量,这一点自己潜意识清楚就可以了。在思考和描述的时候,要是也一个个这么想。会给思考带来一定的困难。而用上面的这种思考和描述方式。就简单得多了,这种思考方式就是面向对象,类似上面面向过程那样的一句话就是:什么时候  谁 做什么。

  面向过程是:什么时候,做什么,怎么做
  面向对象是:什么时候,什么东西,做什么。在面向对象的时候少了一个怎么做 那是因为面向对象的前提是你已经知道怎么做了,这也是我们为什么总是先学习面向过程 如果我们一件事情 怎么做都不知道,就谈不上什么思考模式了。其实对于 图像处理函数就是基于面向对象思考模式开发的 从头到尾都是对这张图片做什么,思考模式,并不局限于书写方式,并不是说这么写就是面向对象 那样写 就是面向过程, 在我们精通了各种功能的实现手法以后。我们往往会通过封装来重复使用代码。那怎么封装更合理呢。 这个时候,看思考方式,之前说过。思路描述,要能和代码吻合。那么封装就不是随意的封装了,封装好的函数和类, 用起来的时候最好能和思考描述的一样,是书写格式。。和思路描述。。尽可能的吻合。 

 比如,我把刚才读取文件的过程。封装成一个函数 
<span function</span> read(<span $file</span><span ) {

}

</span><span //</span><span 读取文件</span>
<span $data</span> = read(<span $file</span>);

符合度百分之百,当然前提你得知道怎么封装这样一个函数,在此由于$file是文件名 将它视为文件有点牵强,但我们可以理解为文件的路径path,所以 最好使用类去封装。

  用我们日常生活的常识来理解对象的话 对象时一个个实体,那么它对应的就应该有一些特性,比如说文件名是什么,路径是多少,文件大小多少,比如说我们人 有身高体重名字性别,但是,在我们平时的制作手法里面。我们要知道一个文件大小。就必须用 filesize 函数去取得。这就像我问你身高是多少,你每次都要重新量一下。 这和我们常识中的对象,存在一定的差距,使得我们在思考描述代码的时候。代码的符合度不够。 但是类可以暂时记住这些特征值,我们称之为对象的属性,属性,一定是一个准确的值,而过程在类里面称为方法,类里面 可以声明一些特殊的变量,这些变量外部不能直接访问到,这些就是类的属性,要想访问一个类的属性和方法一样使用-> 但是不需要写$,假如我们有一个file类 有一个属性

<span $file</span> = <span new</span> <span file</span><span ();
</span><span echo</span> <span $file</span>->size;

用这种方式来访问一个对象变量的属性 怎么定义它 我们先不急 慢慢道来 ,我们先回到思路上,今天我们封装一个文件读写类 我们的代码在需要文件读写的时候我们这样思考:读取文件 处理数据 写入文件 ,这个思路正是文件型计数器的思路。

那么,我们最好的写法是

<span $data</span> = read(<span $file</span><span );
</span><span $data</span> +=1<span ;
write(</span><span $file</span>, <span $data</span>);
    <span function</span> read(<span $file</span><span ) {
        </span><span $fp</span> = <span fopen</span>(<span $file</span>, "r"<span );
        </span><span $data</span> = <span fread</span>(<span $fp</span>, <span filesize</span>(<span $file</span><span ));
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $data</span><span ;
    }
    
    </span><span function</span> write(<span $file</span>, <span $data</span><span ) {
        </span><span $fp</span> = <span fopen</span>(<span $file</span>, "w"<span );
        </span><span $rs</span> = <span fwrite</span>(<span $fp</span>, <span $data</span><span );
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $rs</span><span ;
    }</span>

 这两个函数。都是同属于文件操作的。我们把它封装成为类

<span class</span><span  fileclass {
    
    </span><span function</span> read(<span $file</span><span ) {
        </span><span $fp</span> = <span fopen</span>(<span $file</span>, "r"<span );
        </span><span $data</span> = <span fread</span>(<span $fp</span>, <span filesize</span>(<span $file</span><span ));
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $data</span><span ;
    }
    
    </span><span function</span> write(<span $file</span>, <span $data</span><span ) {
        </span><span $fp</span> = <span fopen</span>(<span $file</span>, "w"<span );
        </span><span $rs</span> = <span fwrite</span>(<span $fp</span>, <span $data</span><span );
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $rs</span><span ;
    }

}<br /><br /></span>

调用这个类的时候。代码是这么写的。

<span $fc</span> = <span new</span><span  fileclass();<br />//读取文件
</span><span $data</span> = <span $fc</span>->read(<span $file</span><span );
</span><span $data</span> +=1<span ;<br />//写入文件
</span><span $fc</span>->write(<span $file</span>, <span $data</span>);
然而这里有个和思路不符的地方,上下的两个$file可以是两个不同的文件,也就是说我可以从文件A读取内容写入到文件B中,但是这样一来就是两个文件,就是两个对象,这个和思路不符,在这个代码中,我们没办法准确的描述出。哪一个量。可以视为这个文件。 尽管使用了类从思维上还是面向的过程,之前说过 作为对象应该有自己的属性,对象 应该知道自己的属性,我们希望 用一个实例化的量 来表示这个对象,一个对象 一旦出现就知道自己的属性,就如我们都知道的姓名和性别,要做到这几点,我们需要修改类的结构,一开始就知道。。就是说。一开始就得知道文件名。而且一开始就要读取文件大小。 毕竟,没有这些过程 不可能凭空得到。在类里面。构造函数可以帮我们做到这一点。构造函数。会在类实例化的时候立即执行。我们可以在构造函数里读取文件的大小,要读取文件大小,同样需要知道文件名。 这就需要一个条件。可以通过函数参数传入。
   <span public</span> <span function</span> __construct(<span $file</span><span ) {
        </span><span $size</span> = <span filesize</span>(<span $file</span><span );
    }</span>
 我们都知道,自定义函数内部变量和外部变量。不是同一个世界的。 也就是说。在这里给 $size 赋值。属性 size 是得不到的。 在这里 在类的方法里面,要想访问类的属性和其他方法。需要用关键字 $this->
<?<span php
</span><span class</span><span  fileclass {
    
    </span><span public</span> <span $size</span> = 0<span ;
     </span><span public</span> <span $name</span> = ''<span ;

    
    </span><span public</span> <span function</span> __construct(<span $file</span><span ) {
        </span><span $size</span> = <span filesize</span>(<span $file</span><span );
        </span><span $this</span>->size = <span $size</span><span ;
         </span><span $this</span>->name = <span $file</span><span ;
    }

    </span><span function</span> read(<span $file</span><span ) {
        </span><span $fp</span> = <span fopen</span>(<span $file</span>, "r"<span );
        </span><span $data</span> = <span fread</span>(<span $fp</span>, <span filesize</span>(<span $file</span><span ));
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $data</span><span ;
    }
    
    </span><span function</span> write(<span $file</span>, <span $data</span><span ) {
        </span><span $fp</span> = <span fopen</span>(<span $file</span>, "w"<span );
        </span><span $rs</span> = <span fwrite</span>(<span $fp</span>, <span $data</span><span );
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $rs</span><span ;
    }

}
</span><span $fc</span> = <span new</span> fileclass("test.txt"<span );

</span><span echo</span> "文件名:" . <span $fc</span>-><span name;
</span><span echo</span> "文件大小:" . <span $fc</span>-><span size;

</span>?>

 

现在回到read方法 既然他已经有属性 知道自己名字和大小了 那在这里就不用再传文件名进去了,

    <span function</span><span  read() {
        </span><span $fp</span> = <span fopen</span>(<span $this</span>->name, "r"<span );
        </span><span $data</span> = <span fread</span>(<span $fp</span>, <span filesize</span>(<span $this</span>-><span size));
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $data</span><span ;
    }
    </span>
 同样的。写入的时候。也不需要再通知文件名了。
<span class</span><span  fileclass {
    
    </span><span public</span> <span $size</span> = 0<span ;
    </span><span public</span> <span $name</span> = ''<span ;
    
    </span><span public</span> <span function</span><span  __construct($file) {
        </span><span $size</span> = <span filesize</span>(<span $file</span><span );
        </span><span $this</span>->size = <span $size</span><span ;
        </span><span $this</span>->name = <span $file</span><span ;
    }

    </span><span function</span><span  read() {
        </span><span $fp</span> = <span fopen</span>(<span $this</span>->name, "r"<span );
        </span><span $data</span> = <span fread</span>(<span $fp</span>, <span filesize</span>(<span $this</span>->name<span ));
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $data</span><span ;
    }
    
    </span><span function</span> write(<span $data</span><span ) {
        </span><span $fp</span> = <span fopen</span>(<span $this</span>->name, "w"<span );
        </span><span $rs</span> = <span fwrite</span>(<span $fp</span>, <span $data</span><span );
        </span><span fclose</span>(<span $fp</span><span );
        </span><span return</span> <span $rs</span><span ;
    }

}</span>
 现在,整个类就变成了这个样子。 回到刚才的计数器代码。 
<span $fc</span> = <span new</span> fileclass("test.txt"<span );
//读取文件
</span><span $data</span> = <span $fc</span>-><span read();

</span><span $data</span> +=1<span ;
</span><span echo</span> <span $data</span><span ;
//写入文件
</span><span $fc</span>->write(<span $data</span>);
 由于读取是一个过程,也就是一个方法。从哪读取的? $fc  $fc 此时,可以完全的理解为。就是文件本身了。   总结下:面向对象这种思维方式。讲究的是:什么时候,什么东西,做什么 。为了能让代码书写的时候,更符合这种描述方式,我们需要把过程封装起来。而类。只不过是为了能更准确的符合这种思考描述方式而做的准备性封装,不是说用类就是在用 面向对象 编程了。一个类写出来以后。如果在使用的过程中。不符合面向对象的思维方式。。那也只是普通的类,面向对象思维方式。。一定要有准确的对象。。可以把某个量。视为一个实体的东西。也就是“对象” 。归根到底其实是先有思路才有类的。

 
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn