【问题标题】:OOP concept understandingOOP概念理解
【发布时间】:2015-11-05 14:00:01
【问题描述】:

我最近开始学习 PHP 中 OOP 的基础知识。

我对很多概念都很陌生。

在传统的程序化做事方式中,如果我有重复的任务,我会编写一个函数并每次调用它。

因为这似乎是经常发生的事情,所以我创建了一个包含 5-10 个函数的小型库,我将其包含在我的程序项目中并使用了。

在 OOP 中,使用函数并让所有对象都可以访问它们的有效方式是什么?

为了让事情更接近真实世界,我创建了一个缩略图类,它以图像文件名作为参数并可以对其执行一些操作。

在过程编程中。当我有一个创建缩略图的功能时,我还有一个创建随机 md5 字符串的功能,检查给定文件夹是否存在所述字符串,如果存在则重复,这样我就可以在保存之前为我的缩略图生成一个唯一的名称。

但如果我想为另一个目的生成另一个唯一名称,比如保存一个文本文件,我可以再次调用该函数。

那么,长话短说,让我的应用程序中的所有对象都可以访问 randomise_and_check($filename) 方法(以及我的库中的所有其他方法)的有效 OOP 方法是什么?

【问题讨论】:

  • 虽然我能理解你提出问题的原因,但目前的答案让我想开始一场关于是否应该使用 static 方法的宗教书呆子战争。关于依赖注入和静态方法的整个争论只是渴望爆发。因此,我认为您的问题可能会“征求意见、辩论、论据、投票或扩展讨论”,并且可能比programmers.stackexchange.com 更好。
  • 这与我的实际意图相去甚远。毕竟,我怎么知道我的问题的答案是有争议的,因为我在问,因此不知道答案是什么?
  • @rdlowrey:哈哈!让游戏开始。众所周知,有 100 种方法可以给众所周知的猫剥皮,通过让他接触几个不同的选项,他可以选择他觉得最舒服的选项和 gitrdone。
  • 你的问题没有错。只是我不认为有一个普遍接受的正确答案——只是不同程度的好或坏答案。这是一个好问题,,但我认为 SO 不是适合它的论坛。其他人可能不同意我的观点,这也很好。在这一点上,有一些高质量的答案,所以无论如何它都非常有用。

标签: php oop


【解决方案1】:

很好的问题。您要做的第一件事是确定您将使用的主要对象。一个简单的方法是识别与您的项目相关的所有名词。在您的示例中,听起来您将使用图像和字符串,由此我们可以创建两个包含相关属性(函数、成员变量等)的类。正如您明智地提到的那样,我们需要确保您转换为 OOP 的算法可以从任何上下文中调用,因此我们尽量使它们保持抽象(在合理范围内)。

因此,对于您的具体情况,我建议您:

// Good object reference, abstract enough to cover any type of image
//  But specific enough to provide semantic API calls
class Image
{
    // Using your example, but to ensure you follow the DRY principle
    //  (Don't repeat yourself) this method should be broken up into two
    //  separate methods
    public static function randomise_and_check($fileUri)
    {
        // Your code here
        ....

        // Example of call to another class from within this class
        $hash = String::generateHash();
    }    
}

// Very abstract, but allows this class to grow over time, by adding more 
//  string related methods
class String
{
    public static function generateHash()
    {
        return md5(rand());
    }
}

// Calling code example
$imageStats = Image::radomise_and_check($fileUri);

还有其他几种方法和想法可以使用,例如是否要实例化对象,或者我们是否应该创建一个可以从中扩展的父类,但随着时间的推移和实践,这些概念将变得显而易见。我认为提供的代码 sn-p 应该让您很好地了解如何从程序性跳转到 OOP。而且,一如既往,别忘了阅读docs 了解更多信息。

-- 更新--

添加 OOP 示例:

class Image
{
    protected $sourceUri;

    public function setSourceUri($sourceUri)
    {
        $this->sourceUri = $sourceUri;
    }

    public function generateThumb()
    {
        return YourGenerator::resize($this->getSourceUri);
    }
}

$image = new Image();

$image->setSourceUri($imageUri);

$thumbnail = $image->generateThumbnail();

【讨论】:

  • +1 因为这是一个很好的答案。这并不意味着我必须撤销我的近距离投票!
  • 这是过程式编程,不是 OOP。仅仅因为您使用类并不意味着它是面向对象的。您的代码片段中甚至没有一个对象。
  • @tereško:你是看文字还是只看代码?代码片段中有两个对象,String 和 Image,都可以实例化和扩展。鉴于他在 OP 中发布的示例,我认为静态方法会是一个更好的示例,因为在 imo 中,不需要实例化对象只是为了调整图像大小或创建哈希字符串。
【解决方案2】:

在我看来,你有两个选择:

  • 不要担心把自己塞进 OOP 中,只需将它们作为标准的全局函数,放在一些你想使用它的地方的实用程序.php 文件中。这是我的首选方法。

  • 如果您采用更多面向对象的方法,您可以在某些实用程序类中将它们设为static 函数(“方法”)。来自 PHP 文档:

    <?php
    class Foo {
        public static function aStaticMethod() {
            // ...
        }
    }
    
    Foo::aStaticMethod();
    $classname = 'Foo';
    $classname::aStaticMethod(); // As of PHP 5.3.0
    ?>
    

【讨论】:

  • 不是我坚持什么,我只是想知道什么是正确的做法。
【解决方案3】:

使用静态函数创建一个(抽象的)Util 类:

我的 Util 类的示例:

abstract Class Util{

   public static function dump($object){
       echo '<pre class=\"dump\">' . print_r($object, true) . '</pre>';
   }

}

使用方法:

<?
$object = new Whatever();
//what's in the object?
Util::dump($object);
?>

【讨论】:

    【解决方案4】:

    对于初学者来说,OOP 开发与程序开发并没有什么不同(一旦您掌握了基本概念,就会有很大不同,但这对于学习基础知识并不重要)。

    您一直在处理 OO 概念,只是您没有意识到这一点。当您单击文件管理器中的文件并操作该文件时..您正在使用面向对象的概念。该文件具有属性(大小、类型、只读等)以及您可以使用它执行的操作(打开、复制、删除)。

    您只需通过创建具有属性的对象和可以用它做的事情(方法)来将这些概念应用到开发中。

    在 OOP 世界中,您通常不会将事物提供给其他所有事物。 OOP 是关于“封装”的,它限制对只需要的访问。为什么要为橙汁对象提供“理发”方法?你不会的。您只使“理发”方法可用于需要理发的对象。

    【讨论】:

    • 我明白了。所以建议是我将方法添加到每个具有含义的对象中?
    • @AnPel - 不一定。大多数函数可以归结为使用单一类型的对象(或继承情况下的类型)。如果一组代码非常通用,可以处理许多不同类型的对象,那么它可能是它自己类型的一个很好的候选者。在您的示例中,其中一些函数属于 Thumbnail 对象,但其他函数属于更通用的 File 对象。例如,md5 例程属于文件而不是缩略图。
    【解决方案5】:

    编写可重用的 OO 软件非常困难。很多时候,即使是专业人士也无法做到这一点。在某些情况下,这需要经验、培训、实践和坦率地说是运气的结合。

    您应该阅读有关依赖注入的信息,因为它似乎适用于您的特定问题。基本上,您有一个依赖于某种抽象的对象,可能是“图像库”功能。在您的控制器中,您将创建一个“图像库”对象的实例,并将该依赖项注入到任何其他需要它的对象中。

    也就是说,您需要完全停止考虑全局范围。相反,您必须以理智的方式划分功能并将它们联系在一起。基本上,对象应该只知道他们需要知道的部分(也可以查看 Demeter 和 SOLID 定律)。我重申,这很难正确完成,而且大多数情况下,即使操作不正确,您仍然可以拥有一个运行良好的应用程序。

    如果你想对此非常严格,你应该将这种思路应用到所有事情上,但是如果你有一个像return isset($_POST[$key]) ? $_POST[$key] : $default; 这样包装非常简单的函数的函数,我认为为此创建一个全局函数并没有真正的危害。您可以创建一个HttpPost 包装类,但在大多数情况下,这在 IMO 中是多余的。

    【讨论】:

      【解决方案6】:

      简短的回答:使用普通函数。 OOP 鼓励您考虑数据和相关例程,使用静态函数而不是普通函数不会使您的程序更加面向对象。遵循单一的编程范式是不切实际的,当你看到这将使你的程序更干净时,将它们组合起来。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多