Как я могу расширить этот абстрактный класс лучшим способом

#php

#php

Вопрос:

Я пытаюсь реализовать класс форматирования валюты для разных валют, таких как евро, доллары и т. Д. Я попытался создать абстрактный класс и хочу расширить классы Euro и Dollerиз этого класса.

Поскольку я новичок в PHP и не знаю, является ли это лучшим способом реализации подобной идеи.

   abstract class Currency {
      private $name;
      private $symbol;
      private $decimal;
      private $decimal_point;
      private $thousand_sep;

      function __construct() {      
      }

      function setName($name) {
          $this->name = $name;
      }
      function getName() {
          return $this->name;
      }

      function setSymbol($symbol) {
          $this->symbol = $symbol;
      }
      function getSymbol() {
          return $symbol;
      }

      function setDecimal($decimal) {
          $this->decimal = $decimal;
      }
      function getDecimal() {
          return $this->decimal;
      }

      function setDecimalPoint($decimal_point) {
          $this->decimal_point = $decimal_point;
      }
      function getDecimalPoint() {
          $this->decimal_point;
      }

      function setThousandSeprator($thousand_sep) {
          $this->thousand_sep = $thousand_sep;
      }
      function getThousandSeprator() {
          return $this->thousand_sep;
      }

      function display() {
          return $this->symbol . number_format($this->amount, $this->decimal, $this->decimal_point, $this->thousand_sep);
      }
  }
  

Комментарии:

1. Просто подсказка: php.net/manual/en/class.numberformatter.php — это из международной библиотеки с открытым исходным кодом, вы можете взглянуть.

Ответ №1:

Знаете ли вы, что PHP5.3 поставляется в комплекте с intl PECL и, следовательно, знает NumberFormatter, который должен быть способен делать то, что вы пытаетесь создать здесь?

 <?php

$value = 9988776.65;

$nf = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $nf->formatCurrency($value, "EUR") . "n";
echo $nf->formatCurrency($value, "USD") . "n";
$nf = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
echo $nf->formatCurrency($value, "EUR") . "n";
echo $nf->formatCurrency($value, "USD") . "n";
  

Комментарии:

1. Я бы настоятельно рекомендовал использовать это решение по следующим причинам: Расширение intl опирается на данные из репозитория CLDR ( cldr.unicode.org/translation/currency-names ), который представляет собой набор официальных форматов для (почти) любой страны. И: гораздо проще переносить и поддерживать эти функции в вашем классе вместо написания классов PHP для каждой валюты, которую вы, возможно, захотите поддерживать в будущем.

Ответ №2:

Я не думаю, что вам нужны все эти установщики, поскольку разделители, десятичные точки и тому подобное не будут меняться в течение срока службы форматера. Если все, что вы хотите, чтобы ваш класс делал, это форматировал currency, я не думаю, что вам нужны все геттеры.

Если ваш класс отвечает только за форматирование, я не думаю, что вам следует сохранять значение в качестве поля класса; может быть, лучше просто передать его в display() качестве аргумента.

Как насчет чего-то подобного:

 abstract class CurrencyFormatter {
    protected $name;
    protected $symbol;
    protected $decimal;
    protected $decimal_point;
    protected $thousand_sep;

    function format($amount) {
        return $this->symbol . number_format($amount, $this->decimal, $this->decimal_point, $this->thousand_sep);
    }
}

class EuroFormatter extends CurrencyFormatter {
    public function __construct() {
        $this->name = "Euro";
        $this->symbol = "E";
        $this->decimal = 2;
        $this->decimal_point = ".";
        $this->thousand_sep = ",";

    }
}
  

Затем вы можете использовать его следующим образом:

 $formattedAmount = new EuroFormatter()->format(123);
  

Ответ №3:

Использование абстрактного суперкласса имеет смысл, когда у вас есть некоторая функциональность, которая будет реализована по-разному подклассами. Например, вы хотите отображать евро и доллар по-разному, тогда вы можете определить абстрактную функцию display() и иметь подклассы, реализующие ее.

 abstract class Currency {
..
..
abstract function display();
}

class Dollar extends Currency {
    function display() {
        //display dollar
    }
}

class Euro extends Currency {
    function display() {
        //display euro
    }
}
  

Ответ №4:

Я бы использовал текущую локаль для отображения соответствующей десятичной точки, разделителя тысяч и т. Д. И Просто использовал number_format() для ее отображения.

В Великобритании мы бы сказали $12,345.67 ; €12,345.67 и £12,345.67 .
Во Франции они сказали бы $12.345,67 ; €12.345,67 и £12.345,67 .
Другими словами, форматирование зависит не от валюты, а от локали.

Однако валюта корневого абстрактного класса — хорошая идея — подклассам, вероятно, потребуется только переопределить $symbol , и они будут делать это следующим образом:

 abstract class Currency {
  abstract private $symbol;
/*...*/
}

class GBP extends Currency {
   private $symbol = "£";
}
  

т. е. для этого нет необходимости в getter / setter, поскольку он не изменится.