PHP面向对象常见的关键字和魔术方法

 

 

在PHP5的面向对象程序设计中提供了一些常见的关键字,用来修饰类、成员属性或成员方法,使他们具有特定的功能,例如final、static、const等关键字。还有一些比较实用的魔术方法,用来提高类或对象的应用能力,例如__call()、__toString()、__autoload等。

自己对部分关键字的理解:

Final:不让儿子继承夫类,也就是说不能够对父类在进行调用,否则将会出错。

①final关键字的应用

final关键字的作用如下:
a.实用final标识的类,不能被继承。
b.在类中使用final标识的成员方法,在子类中不能被覆盖。

在下面的例子中声明一个MyClass类,并使用final关键字标识,MyClass类就是最终的版本。不能有子类,也就不能对它进行扩展。代码如下所示:

1
2
3
4
5
6
7
8
9
10
<?php
    final class MyClass{     //声明一个类,并使用final关键字标识,使其不能有子类
        //成员略
    }
    class MyClass2 extends MyClass{     //声明另一个类并试图去继承final标识的类,结果出错。
        //成员略
    }
?>

该程序运行后输出的结果为:
Fatal error:Class MyClass2 may not inberit from final class(MyClass) //输出错误
在上例中,试图用MyClass2类去继承用final标识的类MyClass时,系统报错。同理,如果在类中的成员方法前加final关键字标识,则在子类中不能覆盖它,被final标识的方法也是最终版本。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
    final class MyClass{     //声明一个类,并使用final关键字标识,使其不能有子类
        final function fun(){
            //方法中的内容略
        }
    }
    class MyClass2 extends MyClass{     //声明另一个类并试图去继承final标识的类,结果出错。
        function fun(){
            //方法中的内容略
        }
    }
?>

该程序运行后输出的结果为:
Fatal error:Cannot ovferride final method MyClass::fun() //系统报错

在上面的代码中声明一个MyClass类,并在类中声明一个成员方法fun(),在fun()方法前使用final关键字标识。又声明一个类MyClass2类去继承MyClass类,并在子类MyClass2中声明一个方法fun()试图去覆盖父类中被final标识的fun()方法时,系统会出现报错信息。

②static关键字的使用

使用static关键字可以将类中的成员标识为静态的,既可以用来标识成员属性,也可以用来标识成员方法。以Person类为例,如果在person类中有一个“$country=’china’”的成员属性,任何一个Person类的对象都会拥有自己的一份$country属性,对象之间不会干扰。而static成员是作为整个类的属性存在,如果将$country属性使用static关键字标识,则不管通过Person类创建多少个对象(甚至可以是没有对象),这个static成员总是唯一存在的,在多个对象之间共享的。因为使用static标识的成员是属于类的,所以与对象实例和其他的类无关。类的静态属性非常类似于函数的全局变量。类中的静态成员时不需要对象而使用类名来直接访问的,格式如下所示:

类名::静态成员属性名;                          //在类的外部和成员方法中都可以使用这种方式访问静态成员属性
类名::静态成员方法名();                     //在类的外部和成员方法中都可以使用这种方式访问静态成员方法

在类声明的成员方法中,因为静态成员时属于类的,而不属于任何对象,所以你不能用$this来引用它,而在php中给我们提供了self关键字,就是在类的成员方法中用来代表本类的关键字。格式如下所示:

self::静态成员属性名;                       //在类中的成员方法中使用这种方式访问本类中的静态成员属性
self::静态成员方法名();                  //在类中的成员方法中使用这种方式访问本类中的静态成员方法

如果在类的外部访问类中的静态成员,可以使用对象引用和使用类名访问,通常使用类名来访问。如果在类内部的成员方法中访问其他的静态成员,通常使用self的形式去访问,最好不要直接使用类名称。在下面的例子中声明一个MyClass类,为了让类中的count属性可以在每个对象中共享,将其声明为static成员,用来统计通过MyClass类一共创建了多少对象。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
    //声明一个类,用来演示如何使用静态成员
    class MyClass{    
        static $count;       //在类中声名一个静态成员属性count,用来统计对象呗创建的次数
        function __construct(){         //每次创建一个对象就会自动调用这个构造方法
            self::$count++;          //使用self访问静态成员count,使其自增1
        }
        static function getCount(){             //声明一个静态方法,在类外面直接使用类名就可以调用
            return self::$count;         //在方法中使用self访问静态成员并返回
        }
    }
    MyClass::$count=0;            //在类外面使用类名访问类中的静态成员,为其初始化赋值0
    $myc1 = new MyClass();       //通过MyClass类创建第一个对象,在构造方法中将count累加1
    $myc2 = new MyClass();       //通过MyClass类创建第二个对象,在构造方法中将count累加1
    $myc3 = new MyClass();       //通过MyClass类创建第三个对象,在构造方法中将count累加1
    echo MyClass::getCount();       //在类外面使用类名访问类中的静态成员方法,获取静态属性的值3
    echo $myc3 -> getCount();       //通过对象也可以访问类中的静态成员方法,获取静态属性值3
?>

上例的MyClass类中,在构造方法内部和成员方法getCount()的内部,都使用self访问本类中使用static标识为静态的属性count,并在类的外部使用类名访问类中的静态属性。可以看到同一个类中的静态成员在每个对象中共享,没创建一个对象静态属性count就自增1,用来统计实例化对象的次数。
另外在使用静态方法时需要注意,在静态方法中只能访问静态成员。因为非静态成员必须通过对象的引用才能访问,通常是使用$this完成的。而静态的方法在对象不存在的情况下也可以直接使用类名类访问,没有对象也就没有$this引用,没有了$this引用就不能访问类中的非静态成员,但是可以使用类名或self在非静态方式中访问静态成员。

③const关键字

虽然const和static的功能不同,但使用的方法比较相似。在PHP中定义常量是通过调用define()函数来完成的,但要将类中的成员属性定义为常量,则只能使用const关键字。将类中的成员属性使用const关键字标识为常量,其访问的方式和静态成员一样,都可以通过类名或在成员的方法中使用self关键字访问,也不能用对象来访问。标识常量的属性是只读的,不能重新赋值,所以在声明常量时一定要给初值,因为没有其他方式后期为常量赋值。在下面的示例中演示了再类中如何声明常量,并在成员方法中使用self和在类外面通过类名来访问常量。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
    //声明一个MyClass类,在类中声明一个常量,和一个成员方法
    class MyClass{
        const CONSTANT = 'CONSTANT value';       //使用const声明一个常量,并直接附上初始值
        function showConstant() {
            echo self::CONSTANT."<BR>";              //使用self访问常量,注意常量前不要加"$"
        }
    }
    echo MyClass::CONSTANT . "<BR>";            //在类外部使用类名称访问常量
    $class = new MyClass();                  //通过类MyClass创建一个对象引用$class
    $class ->showConstant();            //调用对象中的方法
?>

④instanceof关键字

使用这个关键字可以确定一个对象是类的实例、类的子类,还是实现了某个特定接口,并进行相应的操作。例如,假设希望了解名为$man的对象是否为类Person的实例:

1
2
3
4
5
6
7
<?php
    $man =new Person();
        ...
    if($man instanceof Person)
        echo '$man 是Person类的实例对象';
?>

在这里有两点值得注意。首先,类名没有任何定界符(不使用引号),使用定界符将导致语法错误。其次,如果比较失败,脚本将退出执行。instanceof关键字在同时处理多个对象时特别有用,例如,你可能要重复地调用某个函数,但希望根据对象类型调整函数的行为。

⑤clone关键字克隆对象和__clone()魔术方法。

在PHP中可以根据现有对象克隆出一个完全一样的对象,克隆以后原本和副本两个对象完全独立,互不干扰。在PHP5中使用“clone”关键字克隆对象,代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
    class Person{
        private $name;
        private $sex;
        private $age;
        //构造方法在对象诞生时为成员属性付初值
        function __construct($name="",$sex="",$age=1){
            $this ->name = $name;
            $this ->sex = $sex;
            $this ->age = $age;
        }
        //声明此方法则在对象克隆时自动调用,用来为新对象重新赋值
        function __clone(){
            $this ->name ="我是".$that ->name."的副本";     //为副本对象中的name属性重新赋值
            $this ->age =10;
        }
        //一个成员方法用于打印出自己对象中全部的成员属性值
        function say() {
            echo "我的名字:".$this ->name.",性别:".$this ->sex.",年龄:".$this ->age."<br>";
        }
    }
    $p1 = new Person("张三","男",20);
    $p2 = new clone $p1;
    $p1 ->say();          //调用源对象中的说话方法,打印原对象中全部属性值
    $p2 ->say();          //调用副本对象中的说话方法,打印副本对象中全部属性值
?>

改程序运行后输出的结果为:

我的名字:张三, 性别:男,年龄:20
我的名字:我是张三的副本, 性别:男,年龄:10 //副本对象中的name和age都被赋上新值

在上面的程序中一共创建了两个对象,其中有一个对象是通过clone关键字克隆出来的副本。两个对象完全独立,如果需要对克隆后的副本对象在克隆时重新为成员属性赋初值,则可以在类中声明一个魔术方法“__clone()”。该方法时在对象克隆时自动调用的,所以就可以通过此方法对克隆后的副本重新初始化。__clone()方法不需要任何参数,该方法中自动包含$this和$that两个对象的引用,$this是副本对象的引用,$that是原本对象的引用。将上例中的代码改写一下,在类中添加魔术方法__clone(),为副本对象中的成员属性重新初始化。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
    class Person{
        private $name;
        private $sex;
        private $age;
        //构造方法在对象诞生时为成员属性付初值
        function __construct($name="",$sex="",$age=1){
            $this ->name = $name;
            $this ->sex = $sex;
            $this ->age = $age;
        }
        //一个成员方法用于打印出自己对象中全部的成员属性值
        function say() {
            echo "我的名字:".$this ->name.",性别:".$this ->sex.",年龄:".$this ->age."<br>";
        }
    }
    $p1 = new Person("张三","男",20);
    $p2 = new clone $p1;
    $p1 ->say();          //调用源对象中的说话方法,打印原对象中全部属性值
    $p2 ->say();          //调用副本对象中的说话方法,打印副本对象中全部属性值
?>

⑥类中通用的方法__toString()

“魔术”方法__toString()是快速获取对象的字符串标识的最便捷的方式,它是在直接输出对象引用时自动调用的方法。通过前面的介绍我们知道,对象引用是一个指针,即存放对象在堆内存中的首地址的变量。例如“$p=new Person()”语句中,$p就是一个对象的引用,如果直接使用echo输出$p,则会输出错误。如果在类中添加了“__toString()”方法,则直接输出对象的引用时就不会产生错误,而是自动调用了该方法,并输出“__toString()”方法中返回的字符串。所以__toString()方法中一定要有一个字符串作为返回值,通常在此方法中返回字符串是使用对象中多个属性值链接而成的。在下面的例子中声明一个测试类,并在类中添加了__toString()方法,该方法中将成员属性的值转化为字符串后返回。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
    class TestClass{
        private $foo;
        function __construct($foo){
            $this -> foo = $foo;
        }
        public function __toString(){
            return $this ->foo;
        }
    }
    $obj = new TestClass('hello');
    echo $obj;
?>

⑦__call()方法的应用

如果尝试调用对象中不存在的方法,一定会出现系统报错,并推出程序不能继续执行。在PHP中,可以在类中添加一个魔术方法__call(),则调用对象中不存在的方法时就会自动调用该方法,并且程序也可以继续向下执行。所以我们可以借助__call()方法提示用户,例如,用户调用的方法及需要的参数列表不存在。__call()方法需要两个参数:第一个参数是调用不存在的方法时,接收这个方法名称字符串;而参数列表则以数组的形式传递到__call()方法的第二个参数中。下面的例子声明的类中添加了__call()方法,用来解决用户调用对象中不存在的方法的情况。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
    class TestClass{
        function printHello(){
            echo "Hello<br>";
        }
        function __call($functionName,$arge) {
            echo "你所调用的函数:".$functionName."(参数:";
            print_r($arge);
            echo ")不存在!<br>\n";
        }
    }
    $obj = new TestClass();
    $obj -> myFun("one",2,"three");          //调用对象中不存在的方法,则自动调用了对象中的__call()方法
    $obj -> otherFun(8,9);                   //调用对象中不存在的方法,则自动调用了对象中的__call()方法
    $obj -> printHello();             //调用对象中存在的方法,可以成功调用
?>

该程序运行后输出的结果为:
你所调用的函数:myFun(参数:Array([0]=>one ,[1]=>2,[2]=>three))不存在!
你所调用的函数:myFun(参数:Array([0]=>8 ,[1]=>9))不存在!
Hello

⑧__autoload()自动加载类

在设计面向对象的程序开发时,通常为每个类的定义都单独建立一个PHP源文件。当你尝试使用一个未定义的类时,PHP会报告一个致命错误。可以用include包含一个类锁子啊的源文件,毕竟你知道要用哪个类。如果一个页面需要使用多个类,就不得不在脚本页面开头编写一个长长的包含文件的列表,将本页面需要的类全部包含进来。这样处理不仅繁琐,而且容易出错。

PHP提供了类的自动加载功能,这可以节省编程的事件。当你尝试使用一个PHP没有组织到的类时,它会寻找一个__autoload()的全局函数(不是在类中声明的函数)。如果存在这个函数,PHP会用一个参数来调用它,参数即类的名称。

在下例中说明了__autoload()是如何使用的,它假设当前目录下每个文件对应一个类,当脚本尝试来创建一个类User的实例时,PHP会自动执行__autoload()函数。脚本假设user.class.php中定义有User类,不管调用时是大写还是小写,PHP将返回名称小写。所以你做项目时,在组织定义类的文件名时,需要按照一定的规则,一定要以类名为中心,也可以加上同意的前缀或后最形成文件名,比如classname.class.php、xxx_classname.php、lassname_xxx.php或是classname.php等,推荐类文件名使用“classname.class.php”格式。代码如下所示:

1
2
3
4
5
6
7
8
<?php
    function __autoload($className){
        include(strtolower($className)."class.php");
    }
    $obj = new User();         //User类不存在则自动调用__autoload()函数,将类名User作为参数传入
    $obj2 = new Shop();        //Shop类不存在则自动调用__autoload()函数,将类名Shop作为参数传入
?>

⑨serialize()对象串行化

对象通过写出描述自己状态的数值来记录自己,这个过程称对象的串行化。串行化就是把整个对象转化为二进制字符串。在两种情况下必须把对象串行化,如下所示:

a.对象需要在网络中传输时,将对象串行化成二进制串后在网络中传输。
b.对象需要持久保存时,将对象串行化后写入文件或是数据库中。

使用serialize()函数来串行化一个对象,把对象转化为二进制的字符串。serialize()函数需要一个参数就是对象的引用名,返回值为一个对象被串行化后的字符串。另一个是反串行化,就是把对象串行化后转化的二进制字符串再转化为对象,我们使用unserialize()函数来饭串行化一个对象。

在PHP5中还有两个魔术方法__sleep()和__wakeup()可以使用。在调用serialize()函数将对象串行化时,会自动调用对象中的__sleep()方法,用来将对象中的部分成员串行化。在调用unserialize()函数饭串行化对象时,则会自动调用对象中的__wakeup()方法,用来在二进制串重新组成一个对象时,为新对象中的成员属性重新初始化。

__sleep()函数不需要接收任何参数,但需要返回一个数组,在数组中包含需要串行化的属性。未被包含在数组中的属性将在串行化时被忽略。如果没有在类中声明sleep()方法,对象中的所有属性都将被串行化。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
    class Person {
        private $name;
        private $sex;
        private $age;
        function __construct($name="",$sex="",$age=1){
            $this ->name = $name;
            $this ->sex = $sex;
            $this ->age = $age;
        }
        function say() {
            echo "我的名字:".$this ->name.",性别:".$this ->sex.",年龄:".$this ->age."<br>";
        }
        //在类中添加此方法,在串行化时自动调用并返回数组
        function __sleep(){
            $arr = array("name","age");      //数组中的成员$name和$age将被串行化,成员$sex则被忽略
            return($arr);
        }
        //在反串行化对象时自动调用该方法,没有参数也没有返回值
        function __wakeup(){
            $this ->age = 40;        //在重新组织对象时,为新对象中的$age属性重新赋值
        }
    }
    $person1 = new Person("张三","男",20);    
    //把一个对象串行化,返回一个字符串,调用了__sleep()方法,忽略没在数组中的属性$sex
    $person_string=serialize($person_string);
    echo $person_string."<br>";
    //反串行化对象,并自动调用了__wakeup()方法重新为对象中的$age属性赋值
    $person2 = unserialize($person_string);           //反串行化对象形成对象$P2重新赋值$age为40
    $person2 ->say();
?>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在论文中自动生成标准的参考文献格式

首先下载EndNote软件&#xff0c;word中会自动显示EndNote选项 选择EndNote 选择导出会下载一个txt文件 打开EndNote中向下的箭头导入&#xff08;从文件导入文献到库中&#xff09;找到刚才下载的txt文件 点击选择按键找到txt文件 选择打开即可 选择导入 选择导入的内容…

PrincetonAlgorithm I - Assignment2 Deques and Randomized Queues

Programming Assignment2 - Deque and Randomized Queues Review Assignment Specification 课程笔记 Subtext: Modular Programming Stacks and Queues are fundamental data types Value: collection of objectsBasic Operation: insert, remove, iterate.Difference: which …

TCP短连接产生大量TIME_WAIT导致无法对外建立新TCP连接的原因及解决方法—基础知识篇...

最近遇到一个线上报警&#xff1a;服务器出现大量TIME_WAIT导致其无法与下游模块建立新HTTP连接&#xff0c;在解决过程中&#xff0c;通过查阅经典教材和技术文章&#xff0c;加深了对TCP网络问题的理解。作为笔记&#xff0c;记录于此。 备注&#xff1a;本文主要介绍…

开源许可证,欢迎来到云时代

出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013)作者 | 唐建法前言开源许可证从最早的 GPL 开始&#xff0c; 逐渐演进到 GPLv2 和 v3&#xff0c;中间还有 Apache、MPL、AGPL、LGPL 等&#xff0c;但是近几年来有一批新的许可证的出现&#xff0c;引起了社区的一些…

selenium - Select类 - 下拉框

WebDriver提供了Select类来处理下拉框。 如百度搜索设置的下拉框&#xff0c;如下图&#xff1a; from selenium import webdriver from selenium.webdriver.support.select import Select from time import sleepdriver webdriver.Chrome() driver.implicitly_wait(10) drive…

.NET 7 预览版 7

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;12分钟)今天我们发布了 .NET 7 预览版 7。这是 .NET 7 的最后一个预览版&#xff0c;下一个版本将是我们的第一个候选版本 &#xff08;RC&#xff09;。.NET Conf 2022 的日期已经公布&#xff01;请于 2022 年 11 月…

android--------volley之网络请求和图片加载

为什么80%的码农都做不了架构师&#xff1f;>>> Volley是 Google 推出的 Android 异步网络请求框架和图片加载框架。 Volley的特性 封装了的异步的请求API。Volley 中大多是基于接口的设计&#xff0c;可配置性强。一个优雅和稳健的请求队列&#xff0c;一定程度符…

经典算法学习——冒泡排序

冒泡排序是我们学习的第一种排序算法。应该也算是最简单、最经常使用的排序算法了。无论怎么说。学会它是必定的。今天我们就用C语言来实现该算法。演示样例代码已经上传至&#xff1a;https://github.com/chenyufeng1991/BubbleSort算法描写叙述例如以下&#xff1a;&#xff…

Mybatis之设计模式之装饰者模式

了解&#xff0c;什么是装饰者模式? 1.定义 装饰模式是在不必改变原类文件和使用继承的情况下&#xff0c;动态地扩展一个对象的功能。它是通过创建一个包装对象&#xff0c;也就是装饰来包裹真实的对象。 2.特点 1 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真…

一天掌握Android JNI本地编程 快速入门

一、JNI&#xff08;Java Native Interface&#xff09; 1、什么是JNI&#xff1a;JNI(Java Native Interface):java本地开发接口JNI是一个协议&#xff0c;这个协议用来沟通java代码和外部的本地代码(c/c) 外部的c/c代码也可以调用java代码2、为什么使用JNI&#xff1a;效率上…

[转]CentOS 7忘记root密码解决办法

转自&#xff1a;http://www.linuxidc.com/Linux/2016-08/134034.htm 亲测可用&#xff01; CentOS 7 root密码的重置方式和CentOS 6完全不一样&#xff0c;CentOS 7与之前的版本6变化还是比较大的&#xff0c;以进入单用户模式修改root密码为例。 1.重启开机按esc 2.按e 3.编…

美链BEC合约漏洞技术分析

这两天币圈链圈被美链BEC智能合约的漏洞导致代币价值几乎归零的事件刷遍朋友圈。这篇文章就来分析下BEC智能合约的漏洞 <!-- more --> 漏洞攻击交易 我们先来还原下攻击交易&#xff0c;这个交易可以在这个链接查询到。我截图给大家看一下&#xff1a; 攻击者向两个账号转…

vue 公众号扫描_vue编写微信公众号打开相机功能

vue编写微信公众号打开相机功能&#xff0c;什么都不多说直接上代码页面布局代码class"previewer-demo-img":key"index":src"item.src"width"100"click"previewImg(index)">1.微信config初始化前端代码initWxConfig() {l…

SQL Server-聚焦NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL性能分析(十八)

前言 本节我们来综合比较NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL的性能&#xff0c;简短的内容&#xff0c;深入的理解&#xff0c;Always to review the basics。 NOT IN、NOT EXISTS、LEFT JOIN...IS NULL性能分析 我们首先创建测试表 USE TSQL2012 GOCREATE SCHEMA [c…

global using 的另类用法

前言global using 指令在 C# 10 中被引入&#xff0c;意味着 using 将应用于编译中的所有文件&#xff08;通常是一个项目&#xff09;。比如&#xff1a;global using System.Text;则在同一项目的其他位置&#xff0c;可以直接使用 System.Text 下的所有类型而无需再次声明 us…

利用 Node.js 实现 SAP Hana 数据库编程接口

为什么80%的码农都做不了架构师&#xff1f;>>> 自 SAP HANA SP 11 之后&#xff0c;可以使用 Node.js 作为 Hana 的编程接口。SAP 将 Application server 简称为 XS。现在 XS 已经演化为 Advanced 版本。为了区别&#xff0c;早期的 XS 被称为 XS Classical。 从下…

WPF 实现自绘验证码

WPF 实现自绘验证码控件名&#xff1a;VerifyCode作者&#xff1a;WPFDevelopersOrg原文链接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;项目使用 MIT 开源许可协议&#xff1b;如何通过DrawingV…

css中的单位换算_CSS单位px、em、rem及它们之间的换算关系

作者:WangMin格言:努力做好自己喜欢的每一件事国内的设计师大都喜欢用px&#xff0c;而国外的网站大都喜欢用em和rem&#xff0c;那么三者的区别与优势是什么&#xff1f;接下来我们就来学习一下吧&#xff01;单位px、em、rem分别表示什么&#xff1f;1、 px(Pixel) 相对于显示…

【MAC】Ncnn 编译so文件方案

【MAC】Ncnn 编译so文件方案 1、下载ncnn github地址是&#xff1a;https://github.com/Tencent/ncnn 指定目录&#xff1a;在终端或者git管理工具 输入&#xff1a;git clone https://github.com/Tencent/ncnn.git 2、编译Ncnn 2.1 Mac平台 安装cmake、wget&#xff08;根据实…

SSM学习注意杂记

2019独角兽企业重金招聘Python工程师标准>>> 1.spring导包时一定要版本对应&#xff0c;最好不要导不同版本的包&#xff0c;还有mybatis的包&#xff0c;springmvc的包&#xff0c;三个框架的包都需配套&#xff0c;要不然会出现一些想象不到的错误。 2.mybatis写映…