PHP: простой класс-сумматор
Пример того, как обрабатывать методом класса любое количество аргументов (метод plus
),
различать аргументы-числа и строки (конструктор и тот же метод),
выводить данные по формату, заданному свойством класса.
Проверено в XAMPP с PHP 7.3.3.
Хорошее задание по теме - "написать маленький класс, делающий что-нибудь полезное".
<?php class Summa { //Простой класс-сумматор private $sum,$cnt,$fmt="%.3F"; //Формат - как у функции sprintf: //https://www.php.net/manual/ru/function.sprintf.php function __construct ($sum='') { $this->sum = (is_numeric($sum) ? $sum : 0); $this->cnt = (is_numeric($sum) ? 1 : 0); } function plus() { //Количество аргументов функции - любое $numargs = func_num_args(); $arglist = func_get_args(); for ($i=0; $i<$numargs; $i++) if (is_numeric($arglist[$i])) { $this->sum += $arglist[$i]; $this->cnt ++; } } function summa() { return $this->sum; } function count() { return $this->cnt; } function average() { return $this->sum/$this->cnt; } function setFormat ($fmt) { $this->fmt = $fmt; } function format($s) { return sprintf ($this->fmt,$s); } } //end of class Summa //Проверка возможностей класса: $s = new Summa(); //Сумма и количество инициализируются нулями $s->setFormat ('%.2F'); $s->plus(1,2,'test'); $s->plus(3,4); echo 'Sum(s)='.$s->format($s->summa()). ', Avg(s)='.$s->format($s->average()). ', Cnt(s)='.$s->count(); //10.00, 2.50, 4 $d = new Summa(0); //"0" посчитается как число! $d->plus(1); echo '<br>Avg(d)='.$d->format($d->average()); //0.500 ?>
Приведём более современный пример небольшого класса, способного хранить числовые значения в контейнере $vals
и вычислять их простые арифметические и статистические характеристики.
Начиная с PHP версии 5.6 в применении функций func_num_args и func_get_args, в общем, нет необходимости, так как теперь можно передавать массив аргументов с многоточием, как и сделано при вызове конструктора или метода add
. В методе insert
для сравнения оставлен вызов этих функций с целью проверки того, сколько аргументов передано и (при необходимости) выброса исключения.
В классе есть магический метод __toString
, чтобы вернуть его строковое представление, например, для вывода оператором echo
. Пример проверен в XAMPP с PHP 7.4.2.
<!DOCTYPE html> <html lang="ru"> <head> <title>Series</title> <meta charset="utf-8"> </head><body> <?php //Простой класс для статистической обработки чисел: class Series { private $vals, //Массив чисел $fmt; //Формат для вывода function __construct (...$vals) { //...$vals работает с версии PHP 5.6 //Конструктор, в PHP бывает только один у класса $this->vals = []; $this->add ($vals); $this->setFormat(); } function __destruct () { //Деструктор, реально память не освободит $this->vals = []; unset($this->vals); } function __unset($val) { //На всякий случай, т.к. применяем unset к приватным свойствам unset($val); } function __toString() { //"Магический метод" - вернуть строковое представление класса return implode(',',$this->vals); } function add(...$items) { //Добавить любое количество элементов в конец $this->vals = array_merge (array_slice($this->vals,0) , $this->get_array(...$items)); } private function get_array(...$items) { //Сформировать числовой массив из своих аргументов $vals = []; foreach ($items as $item) { if (is_numeric($item)) $vals[] = $item; else if (is_array($item)) { foreach ($item as $subitem) { if (is_numeric($subitem)) $vals[] = $subitem; } } } return $vals; } function insert ($num=0,...$vals) { //Вставить элемент(ы) в позицию $num $numargs = func_num_args(); //До PHP 5.6 - количество аргументов функции $arglist = func_get_args(); //До PHP 5.6 - список аргументов функции if ($numargs < 2 or !is_numeric($arglist[0])) throw new Exception ('Передайте хотя бы 2 аргумента, первый из которых - число'); $cnt = $this->cnt(); if ($num < 0) $num = 0; else if ($num > $cnt) $num = $cnt; $this->vals = array_merge ( array_slice($this->vals,0,$num), $this->get_array(...$vals), array_slice($this->vals,$num) ); } function remove ($val,$all=false) { //Удалить элемент(ы) по значению, $all=true - все вхождения while (($key=array_search($val,$this->vals)) !== false) { unset($this->vals[$key]); if (!$all) break; } } private function swap(&$left, &$right) { if ($left == $right) return; $tmp = $left; $left = $right; $right = $tmp; } function removeIndex ($n1,$n2=-1) { //Удалить элемент(ы) с номерами от $n1 до $n2 включительно if ($n2<0 or $n2==$n1) unset($this->vals[$n1]); else { if ($n1>$n2) $this->swap ($n1, $n2); if ($n1 < 0) $n1 = 0; if ($n2 > $this->cnt()-1) $n2 = $this->cnt()-1; array_splice($this->vals, $n1, $n2-$n1+1); } $this->vals = array_values($this->vals); //Переиндексировать! } function summa () { //Сумма return $this->format(array_sum($this->vals)); } function cnt () { //Количество return count($this->vals); } function average () { //Арифметическое среднее $n = $this->cnt(); return $n==0 ? false : $this->format($this->summa($this->vals) / $n); } function max() { return max($this->vals); } //Максимум function min() { return min($this->vals); } //Минимум function sortAsc() { //Сортировка по возрастанию usort($this->vals,function($a,$b){ return ($a < $b ? -1 : 1); }); } function sortDesc() { //Сортировка по убыванию usort($this->vals,function($a,$b){ return ($a > $b ? -1 : 1); }); } function format ($s) { //Форматировать число return sprintf ($this->fmt,$s); } function setFormat ($fmt = '%.2F') { //Установить нужный формат чисел для вывода //См. https://www.php.net/manual/ru/function.sprintf $this->fmt = $fmt; } } //Пример работы класса: $s = new Series(1,2); //вызов конструктора $s->add(3,array(4,5)); //вызов метода echo '<p>После добавления: '.$s.'</p>'; //неявный вызов метода __toString $s->insert(0,6); $s->insert(1,7); $s->insert($s->cnt(),array(8,9),10); echo '<p>После вставки: '.$s.'</p>'; $s->add(2,1); echo '<p>Добавлено ещё 2 элемента в конец: '.$s.'</p>'; $s->remove(10); $s->remove(1,true); echo '<p>Удалено 3 элемента: '.$s.'</p>'; $s->removeIndex(0); echo '<p>Удален элемент номер 0: '.$s.'</p>'; $s->removeIndex(2,5); echo '<p>Удалены элементы с номерами от 2 до 5: '.$s.'</p>'; echo '<p>Количество='.$s->cnt().'</p>'; echo '<p>Сумма='.$s->summa().'</p>'; echo '<p>Среднее='.$s->average().'</p>'; echo '<p>Минимум='.$s->min().'</p>'; echo '<p>Максимум='.$s->max().'</p>'; $s->sortDesc(); echo '<p>Отсортировано по убыванию: '.$s.'</p>'; $s->sortAsc(); echo '<p>Отсортировано по возрастанию: '.$s.'</p>'; unset($s); //вызов деструктора ?> </body></html>
После добавления: 1,2,3,4,5 После вставки: 6,7,1,2,3,4,5,8,9,10 Добавлено ещё 2 элемента в конец: 6,7,1,2,3,4,5,8,9,10,2,1 Удалено 3 элемента: 6,7,2,3,4,5,8,9,2 Удален элемент номер 0: 7,2,3,4,5,8,9,2 Удалены элементы с номерами от 2 до 5: 7,2,9,2 Количество=4 Сумма=20.00 Среднее=5.00 Минимум=2 Максимум=9 Отсортировано по убыванию: 9,7,2,2 Отсортировано по возрастанию: 2,2,7,9
01.04.2019, 12:53 [2114 просмотров]