• 【类】变量复用,函数复用


    变量复用

    变量复用,适用于以下场景:1,整个项目公用的部分(比如errors);2,一组类要通信,或者同一个类的两个函数之间要通信,通信数据可以用类来定义和约束;

    场景1

    所有错误相关的部分要放在一个类里面,方便查找和使用;

    <?php
    class errors
    {
        const ERROR_PARAMS = 'params error';
        const ERROR_EMPTY_PARAM = 'empty param';
    }
    
    class TestModel
    {
        public function run()
        {   
            $error = errors::ERROR_PARAMS;
            var_dump($error);
            return $error;
        }   
    }
    
    $model = new TestModel();
    $model->run();

    解释,errors是整个项目都可以访问的,可以添加更多的错误消息在里面。

    场景2:

    同一个类的两个函数中间需要通信,我们需要对这种通信定义一下数据结构。

    <?php
    class DataMeta
    {
        public $mobile = '';
        public $message = '';
    }
    
    class Sms
    {
        public function send($mobile, $message)
        {   
            $data = new DataMeta();
            $data->mobile = $mobile;
            $data->message = $message;
    
            if ($this->checkValid($data)) {
                echo "Allow to send
    ";
            } else {
                echo "Not allowed to send
    ";
            }   
        }   
    
        public function checkValid(DataMeta $data)
        {   
            if ($data->mobile && $data->message) {
                return true;
            } else {
                return false;
            }
        }
    }
    
    $model = new Sms();
    $model->send(0, '');
    $model->send(12345678910, 'my test');

    checkValid函数对参数进行了校验,我们使用了一个用于通信的数据类型DataMeta,里面包含了我们所需要的结构化数据。显示定义DataMeta,是为了更好地理解。

    当然使用DataMeta这个类型是有些弊端的,如果这个数据结构有很大的变动(比如字段名相同,但实际的含义已经变化了),那么用数组和注释可能比DataMeta这样的约束要更好一些。

    总结下:

    情况1,有一组数据,需要在函数间传递,并且结构不会有变化的;办法是:可以定义一个MetaClass来约束这组数据。

    情况2,有一组数据,需要在函数间传递,但是结构会经常性变化,则不能使用MetaClass来约束;办法是:用数组和注释来说明;特别地,Stdclass也适合这个场景;

    情况3,有一组数据,需要在函数间传递,结构上只会新增字段,原始字段含义保持;办法是:依然可以用MetaClass来约束。

    以上解释了PHP之间传递某个有结构约束的变量,可以有的方法。

    除此之外,我们希望关心,有些类是完成类似的功能,也遵循一些共同的动作,这些类的函数名是一致的。

    函数约束

    函数约束的解决方案:1,基类派生类;2,接口interface。

    如何区分哪种场景下使用基类派生类,哪种场景下使用interface。

    我个人看法是:

    1,如果能用接口实现最好优先使用接口,继承尽量不要使用;

    2,接口只定义约束,并不包含实现,所以各个类动作很不相同,只用接口来约束需要实现的函数即可(大多数的业务代码就是很不同,用接口比较ok);

    3,如果基类已经有完整的功能,派生类需要自己个性化完成的动作并不太多,使用基类继承类。

    代码片段1:

    实现interface时,未实现interface的函数,会报错。所以使用interface时,定义的函数是必须实现的。

    <?php
    interface SmsInterface
    {
        public function sendSms($abc);
    }
    
    class m1 implements SmsInterface
    {
        public function sendSms($aaa = 'cc')
        {
            var_dump(__CLASS__);
        }
    }
    
    class m2 implements SmsInterface
    {
        public function __construct()
        {
            var_dump(__CLASS__);
        }
    }
    
    $a = new m1();
    $a->sendSms();
    $b = new m2();

    执行时,报错:Fatal error: Class m2 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (SmsInterface::sendSms) in

    代码片段2:

    interface定义的函数不携带参数。

    <?php 
    interface SmsInterface
    {   
        public function sendSms();
    }       
        
    class m1 implements SmsInterface
    {
        public function sendSms()
        {
            var_dump(__CLASS__);
        }
    }       
        
    class m2 implements SmsInterface
    {   
        public function __construct()
        {
            var_dump(__CLASS__);
        }
        public function sendSms()
        {
            var_dump(__CLASS__);
        }
    }
    
    $a = new m1();
    $a->sendSms();
    
    $b = new m2();
    $b->sendSms();

    这段代码,没问题,可以正常执行。

    代码片段3:

    如果interface的函数是携带参数的,那么实现类必须是和interface的函数原型保持一致,也需要携带参数才可以。

    <?php
    interface SmsInterface
    {
        public function sendSms($mobile, $message);
    }
    
    class m1 implements SmsInterface
    {
        public function sendSms()
        {
            var_dump(__CLASS__);
        }
    }
    
    $a = new m1();
    $a->sendSms();

    执行时候报错:Fatal error: Declaration of m1::sendSms() must be compatible with SmsInterface::sendSms($mobile, $message)

    代码片段4:

    <?php
    interface SmsInterface
    {
        public function sendSms($mobile, $message);
    }
    
    class m1 implements SmsInterface
    {
        public function sendSms($mobile, $message)
        {
            var_dump(__CLASS__);
        }
    }
    
    $a = new m1();
    $a->sendSms(123, 'message');

    这段代码没问题,可正常执行。

    代码片段5:

    不再详细展开,有兴趣的自己动手实践下之后的结论。

    关于默认参数:

    a,如果interface的函数有默认参数,实现类也必须实现自己的函数,所以interface的默认参数并不起作用;

    b,实现类如果有默认参数,调用时候走默认参数逻辑没问题;

    关于参数列表不一致:

    如果实现类的参数列表比interface定义的要少,是会报错的;

    如果实现类的参数列表比interface定义的要多,语法上不会报错,也可以使用,另外的解决方案是setField()这样的set函数;

  • 相关阅读:
    数学--数论---欧拉筛 模板
    数学--数论--HDU 5019 revenge of GCD
    数学--数论--HDU 2674 沙雕题
    数学--数论--HDU 2104 丢手绢(离散数学 mod N+ 剩余类 生成元)+(最大公约数)
    数学--数论-- HDU -- 2854 Central Meridian Number (暴力打表)
    数学--数论--HDU 2197 本原串 (推规律)
    数学--数论--HDU 2582 F(N) 暴力打表找规律
    C# 命名规范
    文本分类学习 (十)构造机器学习Libsvm 的C# wrapper(调用c/c++动态链接库)
    文本分类学习 (九)SVM入门之拉格朗日和KKT条件
  • 原文地址:https://www.cnblogs.com/helww/p/8176519.html
Copyright © 2020-2023  润新知