这个demo。差不多php的类的主要知识点都用到了。

public,private关键字,

namespace,use命令空间,

require导入,

interface复用,

abstract抽象类,

trait代码复用

static静态变量及静态方法

extends继承

implements实现

__construct初始化

=====================

Unique.php

<?php
namespace Bookstore\Utils;

trait Unique {
    //static静态属性,类似于其它语言的类变量
    private static $lastId = 0;
    //protected保护属性,仅允许继承类访问
    protected $id;

    public function setId(int $id) {
        //内置函数判断id是否为空,比$id == null要逼格好点
        if (empty($id)) {
            //注意区分$this-和self::$的语法
            $this->id = ++self::$lastId;
        } else {
            $this->id = $id;
            if ($id > self::$lastId) {
                self::$lastId = $id;
            }
        }
    }

    public function getId():int {
        return $this->id;
    }

    //静态方法
    public static function getLastId():int {
        return self::$lastId;
    }

}

?>

Person.php

<?php
namespace Bookstore\Domain;
use Bookstore\Utils\Unique;

//命名空间可以直接use,但如果这个命名空间没有在标准约定位置,且没有自动载入的话,需要使用require来手工定位一下.
require_once __DIR__ . '/Unique.php';

class Person {
    //trait的用法,类内use
    use Unique;
    //protected保护属性,仅允许继承类访问
    protected $firstname;
    protected $surname;
    //private私有属性,不允许类外部直接修改
    private $email;

    //构造函数,初始化类的好地方
    public function __construct(
        $id,
        string $firstname,
        string $surname,
        string $email
    ) {
        $this->firstname = $firstname;
        $this->surname = $surname;
        $this->email = $email;
        //复用trait内的方法代码
        $this->setId($id);
    }

    public function getFirstname():string {
        return $this->firstname;
    }

    public function getSurname():string {
        return $this->surname;
    }

    public function getEmail():string {
        return $this->email;
    }
    //类的部通过public方法更改属性,达到信息封装;类内部通过->修改.
    public function setEmail(string $email) {
        $this->email = $email;
    }
}
?>

Payer.php

<?php
//命名空间
namespace Bookstore\Domain;

interface Payer {
    public function pay(float $amount);
    public function isExtentOfTaxes(): bool;
}
?>

Customer.php

<?php
//命名空间
namespace Bookstore\Domain;

//use Bookstore\Domain\Payer;

require_once __DIR__ . '/Payer.php';

interface Customer {
    public function getMonthlyFee(): float;
    public function getAmountToBorrow(): int;
    public function getType(): string;
}
?>

Basic.php

<?php
namespace Bookstore\Domain;
/*
use Bookstore\Domain\Person;
use Bookstore\Domain\Customer;
use Bookstore\Domain\Payer;
*/

require_once __DIR__ . '/Person.php';
require_once __DIR__ . '/Customer.php';
require_once __DIR__ . '/Payer.php';

class Basic extends Person implements Customer, Payer {
    public function getMonthlyFee():float {
        return 5.0;
    }
    public function getAmountToBorrow():int {
        return 3;
    }
    public function getType(): string {
        return 'Basic';
    }

    public function pay(float $amount) {
        echo "Paying $amount.";
    }

    public function isExtentOfTaxes(): bool {
        return false;
    }
}
?>

Premium.php

<?php
namespace Bookstore\Domain;

/*
use Bookstore\Domain\Person;
use Bookstore\Domain\Customer;
use Bookstore\Domain\Payer;
*/

require_once __DIR__ . '/Person.php';
require_once __DIR__ . '/Customer.php';
require_once __DIR__ . '/Payer.php';

class Premium extends Person implements Customer, Payer {
    public function getMonthlyFee():float {
        return 10.0;
    }
    public function getAmountToBorrow():int {
        return 10;
    }
    public function getType(): string {
        return 'Premium';
    }

    public function pay(float $amount) {
        echo "Paying $amount.";
    }

    public function isExtentOfTaxes(): bool {
        return true;
    }
}
?>

Book.php

<?php
namespace Bookstor\Domain;

class Book {
    public function __construct (
        int $isbn,
        string $title,
        string $author,
        int $available = 0
    ) {
        $this->isbn = $isbn;
        $this->title = $title;
        $this->author = $author;
        $this->available = $available;
    }

    public function getIsbn():int {
        return $this->isbn;
    }

    public function getTitle():string {
        return $this->title;
    }

    public function getAuthor():string {
        return $this->author;
    }

    public function isAvailable():bool {
        return $this->available;
    }

    public function getCopy():bool {
        if ($this->available < 1) {
            return false;
        } else {
            $this->available--;
            return true;
        }
    }

    public function addCopy() {
        $this->available++;
    }

    public function __toString() {
        $result = '<i>' . $this->title . '</i> - ' . $this->author;
        if (!$this->available) {
            $result .= ' <b>Not available</b>';
        } else {
            $result .= " <b>{$this->available}</b>";
        }
        return $result . '<br/>';
    }
}
?>

test.php

<?php
//使用命名空间,易于在大型应用中管理和组织php类.
use Bookstor\Domain\Book;
use Bookstore\Domain\Customer;
use Bookstore\Domain\Person;
use Bookstore\Domain\Basic;
use Bookstore\Domain\Premium;
use Bookstore\Utils\Unique;

//命名空间可以直接use,但如果这个命名空间没有在标准约定位置,且没有自动载入的话,需要使用require来手工定位一下.
require_once __DIR__ . '/Unique.php';
require_once __DIR__ . '/Book.php';
require_once __DIR__ . '/Customer.php';
require_once __DIR__ . '/Person.php';
require_once __DIR__ . '/Basic.php';
require_once __DIR__ . '/Premium.php';

$book1 = new Book("1984", "George Orwell", 9785267006323, 12);
$book2 = new Book("1984", "George Orwell", 9785267006323);

$customer1 = new Basic(5, 'John', 'Doe', 'johndoe@mail.com');
//$customer2 = new Customer(null, 'Mary', 'Poppins', 'mp@mail.com');
$customer3 = new Premium(7, 'James', 'Bond', '007@mail.com');

if ($book1->getCopy()) {
    echo 'Sale 1 copy.<br/>';
} else {
    echo 'can not sale.<br/>';
}
//数据类型转换,天下语言几乎大同.
$string1 = (string)$book1;
$string2 = (string)$book2;
echo $string1;
echo $string2;
//调用类的静态方法,可以直接用类名,也可以用实例名.但都是用::符号.
echo Person::getLastId();
echo '<br/>';
echo $customer1::getLastId();

function checkIfValid(Customer $customer, array $books):bool {
    return $customer->getAmountToBorrow() >= count($books);
}
echo '<br/>';
var_dump(checkIfValid($customer1, [$book1]));
echo '<br/>';
var_dump(checkIfValid($customer3, [$book1]));
echo '<br/>';
$basic = new Basic(1, "name", "surname", "email");
$premium = new Premium(2, "name", "surname", "email");
var_dump($basic->getId());
echo '<br/>';
var_dump($premium->getId());
echo '<br/>';
var_dump(Person::getLastId());
echo '<br/>';
var_dump(Unique::getLastId());
echo '<br/>';
var_dump(Basic::getLastId());
echo '<br/>';
var_dump(Premium::getLastId());
echo '<br/>';
//判断父类及继承关系
var_dump($basic instanceof Basic);
echo '<br/>';
var_dump($premium instanceof Basic);
echo '<br/>';
var_dump($basic instanceof Customer);
echo '<br/>';
var_dump($premium instanceof Payer);
echo '<br/>';
var_dump($basic instanceof Payer);
echo '<br/>';

function processPayment($payer, float $amount) {
    if ($payer->isExtentOfTaxes()) {
        echo "What a lucky one...";
    } else {
        $amount *= 1.16;
    }
    $payer->pay($amount);
}

//多态实现
processPayment($basic, 2000);
echo '<br/>';
processPayment($premium, 2000);
echo '<br/>';

?>

输出:

Sale 1 copy.
George Orwell - 9785267006323 11
George Orwell - 9785267006323 Not available
7
7
bool(true)
bool(true)
int(1)
int(2)
int(7)
int(0)
int(7)
int(7)
bool(true)
bool(false)
bool(true)
bool(false)
bool(false)
Paying 2320.
What a lucky one...Paying 2000.

php的类使用样例的更多相关文章

  1. Scala模式匹配和样例类

    Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句.类型检查等.并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配. 1.字符匹配     def mai ...

  2. OpenCV LDA(Linnear Discriminant analysis)类的使用---OpenCV LDA演示样例

    1.OpenCV中LDA类的声明 //contrib.hpp class CV_EXPORTS LDA { public: // Initializes a LDA with num_componen ...

  3. 【Scala篇】--Scala中Trait、模式匹配、样例类、Actor模型

    一.前述 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大. 模式匹配机制相当于java中的switch-case. 使用了case关键字的类定义就是样例类(case ...

  4. Scala--模式匹配和样例类

    模式匹配应用场景:switch语句,类型查询,析构,样例类 一.更好的switch val ch :Char = '+' val sign = ch match{ case '+' => 1 c ...

  5. Scala-Unit6-final/type关键字、样例类&样例对象

    一.关键字 1.final关键字 用final修饰的类:不能被继承 用final修饰的方法:不能被重写 注意:(1)在Scala中变量不需要用final修饰,因为val与var已经限制了变量是否可变 ...

  6. Scala基础:模式匹配和样例类

    模式匹配 package com.zy.scala import scala.util.Random /** * 模式匹配 */ object CaseDemo { def main(args: Ar ...

  7. Java线程演示样例 - 继承Thread类和实现Runnable接口

    进程(Process)和线程(Thread)是程序执行的两个基本单元. Java并发编程很多其它的是和线程相关. 进程 进程是一个独立的执行单元,可将其视为一个程序或应用.然而,一个程序内部同事还包括 ...

  8. Scala学习十四——模式匹配和样例类

    一.本章要点 match表达式是更好的switch,不会有意外调入下一个分支 如果没有模式能够匹配,会抛出MatchError,可以用case _模式避免 模式可以包含一个随意定义的条件,称做守卫 你 ...

  9. 学好Spark/Kafka必须要掌握的Scala技术点(二)类、单例/伴生对象、继承和trait,模式匹配、样例类(case class)

    3. 类.对象.继承和trait 3.1 类 3.1.1 类的定义 Scala中,可以在类中定义类.以在函数中定义函数.可以在类中定义object:可以在函数中定义类,类成员的缺省访问级别是:publ ...

随机推荐

  1. 2018-2019-2 20165315《网络对抗技术》Exp7 网络欺诈防范

    2018-2019-2 20165315<网络对抗技术>Exp7 网络欺诈防范 一.实验内容 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有 简单应 ...

  2. Mysql 查看连接数,状态 最大并发数,以及设置连接数

    show variables like '%max_connections%'; 查看最大连接数 set global max_connections=1000  重新设置最大连接数 set-vari ...

  3. 使用另一个版本的glibc

    glibc是Linux系统的核心库,稍有不慎就会导致系统崩溃.如果在程序中必须使用另一版本的glibc,则需要小心从事.具体来言,是在编译时指定--rpath和--dynamic-linker,而在运 ...

  4. C/C++ static 关键字

    在 C/C++ 中,static 关键字使用恰当能够大大提高程序的模块化特性. static 在 C++ 类之中和在类之外的作用不一样,在C语言中的作用和在 C++ 类之外的作用相同,下面一一说明: ...

  5. 1082 射击比赛 PAT (Basic Level)

    题目链接: https://pintia.cn/problem-sets/994805260223102976/problems/994805260990660608 分析: 这是典型的给出编号和得分 ...

  6. LocalDateTime代替Date

    为什么需要LocalDate.LocalTime.LocalDateTime Date如果不格式化,打印出的日期可读性差 Tue Sep 10 09:34:04 CST 2019 使用SimpleDa ...

  7. Django 模板语言 变量名称

    Django 模板语言 变量名称 模板语言中已变量形式显示 # view 文件内 def func(request): return render(request,"index.html&q ...

  8. Java多线程分批发送消息的小例子

    需求: 假设有10万个用户,现在节假日做活动,需要给每个用户发送一条活动短信,为了提高程序的效率,建议使用多线程分批发送. 这里值得注意的是: 每开一个线程都会占用CPU的资源,所以线程根据所需要的条 ...

  9. C#使用HttpWebRequest发送数据和使用HttpWebResponse接收数据的一个简单示例

    新建一个.NET Core控制台项目,代码如下所示: using System; using System.Text; using System.Net; using System.Collectio ...

  10. systemd - CentOS 7进程守护&监控

    需求: 运行环境为CentOS 7系统,我们开发了一个程序,需要在开机时启动它,当程序进程crash或者开机之后,守护进程立即拉起进程. 解决方案: 使用CentOS 7中的init进程systemd ...