是否有理由为单一功能创建类?

时间:2011-06-20 21:00:00

标签: php class function

我见过很多带有 SINGLE 功能的课程。他们为什么要把SINGLE函数放到课堂上?

我使用类只是为了让事情变得更清楚,但关于那些将SINGLE函数放入类中的人?有什么理由吗?

我认为这些没有区别:

<?php
class Image {
    private $resource;
    function resize($width, $height) {
        $resized = imagecreatetruecolor($width, $height);
        imagecopyresampled($resized, $this->resource, 0, 0, 0, 0, $width, $height, imagesx($this->resource), imagesy($this->resource));
        $this->resource = $resized;
    }
}
$image = new Image();
$image->resource = "./someimage.jpg";
$image->resize(320, 240);

和     

    function resize($width, $height) {
        $resource = "./someimage.jpg";    
        $resized = imagecreatetruecolor($width, $height);
        imagecopyresampled($resized, $resource, 0, 0, 0, 0, $width, $height, imagesx($resource), imagesy($resource));
        $resource = $resized;
        return $resource;
    }

resize(320, 240);

我的想法是$资源是主要原因,因为它是私有的:

class Image {
    private $resource;
    function resize($width, $height) {
        $resized = imagecreatetruecolor($width, $height);
        imagecopyresampled($resized, $this->resource, 0, 0, 0, 0, $width, $height, imagesx($this->resource), imagesy($this->resource));
        $this->resource = $resized;
    }
}

$image->resize(320, 240);

因此无法访问全局范围。但为什么不是这种情况下使用的简单函数呢?

10 个答案:

答案 0 :(得分:28)

类不只是“函数容器”,它们代表一个对象,一个实体。它们应该使用适合它的方法封装给定实体所需的数据。

有时候可能有一类对象只需要为它定义一个方法,但它只属于那个对象类。

答案 1 :(得分:9)

我主要做嵌入式编程,很少使用类。但是单个函数类可能会用于 -

  • 稍后继承
  • 强制执行类专用的数据结构(封装)的完整性。
  • 可用于维护代码的同质性。

答案 2 :(得分:7)

为什么有些函数只有一行代码?因为这就是所需要的。现在你可以调用函数而不是在任何地方重复单行代码。如果需要调整该行代码,则只需在一个地方进行。这是利用程序封装。

您的简短课程也是如此。您现在可以利用所有类可以执行的操作,尤其是继承和多态,例如SVGImage extends Image和覆盖方法resize

实现必要功能所需的最小行数。

答案 3 :(得分:6)

不要将类视为函数集合,而是根据类的角色进行思考。类通常应该知道它包含什么,而不知道它不包含什么,并且应该只捕获一个关键的抽象。可能存在有意义的情况。

答案 4 :(得分:5)

这实际上是一个很好的问题,我在这里看到了一些好的答案。实际上我真的不得不考虑一下这个。

我想在这里添加一些我没有在其他任何答案中看到的东西,即使我没有得到任何选票,这样未来的读者也可以受益。

我们来看看你的例子吧。 (我对它们进行了编辑,使它们在功能上完全相同 - 它们与上面的内容略有不同。)

班级版本:

<?php
class Image {
    private $resource;
    function resize($width, $height) {
        $resized = imagecreatetruecolor($width, $height);
        imagecopyresampled($resized, $this->resource, 0, 0, 0, 0, $width, $height, imagesx($this->resource), imagesy($this->resource));
        $this->resource = $resized;
    }
}
$image = new Image();
$image->resource = "./someimage.jpg";
$image->resize(320, 240);

功能版本:     

    function resize($width, $height, $resource) {
        $resized = imagecreatetruecolor($width, $height);
        imagecopyresampled($resized, $resource, 0, 0, 0, 0, $width, $height, imagesx($resource), imagesy($resource));
        $resource = $resized;
        return $resource;
    }

resize(320, 240, "./someimage.jpg");

在实践中,这些功能相同。主要区别在于OOP范式与程序范式;在OOP中,您在类中定义一个函数(这称为方法),该函数作用于成员变量,而在过程程序中,您将该变量传递给全局范围中定义的函数。

那么,将一个函数包装在一个类中而不是使它成为全局函数有什么好处,因为该函数仍然做同样的事情?

您希望在PHP(以及我能想到的许多其他语言)中执行此操作的主要原因是范围。 @Headspin简要地提到了这一点。在全局范围内定义resize函数一切都很好......直到您需要另一个具有相同名称的函数。会发生什么?

通常,您会遇到以下解决方案之一:

  1. (好的。)你的语言支持函数重载,所以只要你的论点不同,你就不用担心它。
  2. (糟糕。)您的语言不支持函数重载(或者您的参数必须相同),因此您需要使用详细的命名(如resize_imageresize_container)等。< / LI>
  3. (还不错。)您开始使用命名空间来分隔全局函数。
  4. (丑陋的。)你的函数接受任何作为参数的东西,并成为它将处理的每个变量类型的if / then语句或switch / case块的热门,臃肿的混乱。
  5. 我在PHP中封装函数的主要原因是避免命名冲突,使代码更直观,更容易理解。我可以在我的Image类中使用resize方法,并且在Container类中有一个,也可能在test类中有另一个,并且它们都不会与每个类冲突其他。阅读代码,我知道Image->resize()会调用Image类中的方法,而不是其他内容。

    没有名称冲突会带来更多可能性,例如迭代共享公共方法名称的一组对象。 (这是接口发挥作用的地方;阅读它们。)你可以做很多很酷的事情。

    我想就是这样 - 我希望有所帮助。以下是TL; DR版本。

      

    在类中封装单个函数可以防止类似函数的命名冲突,而无需使用命名空间,函数重载或函数重命名。因此,如果您有一个执行泛型任务的函数,最好为函数处理的每个变量类型创建一个类,并将该函数转换为类方法。

答案 5 :(得分:4)

我认为“分类”任何东西的最佳理由,即使是那里的小功能,也只是为了扩展性。也许你需要添加额外的功能才能使其解密图像格式或者你有什么。将其封装到类中将是简化可伸缩性的方法。另外,控制函数和变量的范围总是一个好主意,将它们保持在全局范围内通常不是一个好主意。这只是一种很好的做法,因为当你看似很小的项目突然变成一个大项目时会引起麻烦。

答案 6 :(得分:3)

首先,在您的函数中,您不能将此函数用于任何其他图像文件。这可以通过额外的论证来解决,但是我将跳过这一点。

其次,您可以扩展该类,并添加更多会影响您的设置图像资源的方法。

第三,你可以使用类自动加载器和类,因此只有在实际使用类时才加载包含类的文件,而不是每次运行脚本时加载它或担心放置include和require语句的位置。

第四,也许最重要的是,您可以将此类和任何其他类用作另一个类的输入,从而允许您通过选择要插入的类来更改该类的功能。举个例子......

class ImageProcessingClass {

   protected $imageResource;
   protected $processors = array();

   public function setImageResource($image_resource) {
      $this->imageResource = $image_resource;
   }

   public function addProcessor(Processor $processor) {
      $this->processors[] = $processor;
   }

   public function processImage() {
      foreach ($this->processors as $processor) {
         $this->imageResource = $processor->process($this->imageResource);
      }
   }
}

interface Processor {
   public function process($image);
}

class ProcessorResize implements Processor {

   public function process($image) {
      // resize image code here...
      return $image;
   }
}

class ProcessorFilter implements Processor {

   public function process($image) {
      // filter image code here...
      return $image;
   }
}

以及使用此

的代码
$image_processor = new ImageProcessor();
$image_processor->setImageResource($image_resource);
$image_processor->addProcessor(new ProcessorResize());
$image_processor->addProcessor(new ProcessorFilter());
$image_resource = $image_processor->processImage();

这种模式允许您在影响图像的方式中以不同的结果添加许多不同组合的处理器类。可重用的代码,虽然有类的组合,但有许多不同的可能性。

答案 7 :(得分:1)

根据php中的现代开发,使用Classes非常灵活或强大。

并在全球范围内公开所有功能并不是一个好主意。 所以,为了避免这种情况,我们可以在类中使用静态函数并使用类名调用它。

例如:

Class A{

      public static function xyz(){
       //function handling
      }
}

A::xyz();

答案 8 :(得分:0)

除了上面给出的一些重要原因之外,为什么要将一个方法包装到一个类中,还有一个原因:

在C ++中,如果你想为一个方法提供一个接口,你必须为它定义一个调用。

e.g。

class CallBackClient
{
   public:
   // A callback function. 

  virtual s32 callback( int param1, int param2 ) = 0;
};

每个想要提供自己的回调实现的客户都需要扩展到这个类。

Java为可以“实现”的接口提供直接表示法。

答案 9 :(得分:0)

类就像对象集合,一个实体。类使用适用于它的方法封装给定实体所需的数据并且Object具有一些属性(属性)和方法(Function),它们定义为类的类型 一般方法用于更改属性值。这样每个函数需要类 它的存在。