За последние 24 часа нас посетили 51137 программистов и 3179 роботов. Сейчас ищут 1127 программистов ...

абстрактные классы и наследование

Тема в разделе "PHP для новичков", создана пользователем Dimon2x, 9 апр 2017.

  1. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Вес не включил в базовый, потому что он только в одном месте фигурирует. В принципе, можно и включить. Название сделал приватным, поскольку по-хорошему все поля должны быть или приватными, или защищёнными, но не публичными. Одну нельзя - на уровне базового класса мы знаем только, что может быть скидка, а как она вычисляется - определяется производными классами. У тебя куча функций непонятного назначения, и самое главное - клиентский код точно знает, с каким классом он работает - это неинтересно. Так можно было и вообще не городить всё это наследование. На самом деле, тот код, который я показал, тоже далеко не идеальное решение задачи, но тебе пока показывать самое правильное решение рано, ты бы совсем ничего не понял. Прочитай книжку Зандстры.
     
  2. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    я 100 страниц прочитал
     
  3. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    @Dimon2x, твой код стал лучше, чем был, но есть моменты которые надо улучщить.

    PHP:
    1. header('Content-Type: text/html; charset:utf-8');
    2.  
    3. abstract class Product {
    4.  
    5.     private $title;
    6.     private $price;
    7.     private $weight;
    8.     private $discount = 10;
    9.  
    10.     public function getDiscount() {
    11.         return $this->discount;
    12.     }
    13.  
    14.     public function getPrice() {
    15.         return $this->price - (($this->price * $this->getDiscount()) / 100);
    16.     }
    17.  
    18.     function getPriceWithoutDiscount() {
    19.         return $this->price;
    20.     }
    21.  
    22.     function setTitle($title) {
    23.         $this->title = $title;
    24.     }
    25.  
    26.     function setPrice($price) {
    27.         $this->price = $price;
    28.     }
    29.  
    30.     function setWeight($weight) {
    31.         $this->weight = $weight;
    32.     }
    33.  
    34.     function getWeight() {
    35.         return $this->weight;
    36.     }
    37.  
    38.     public function __construct($title, $price, $weight) {
    39.         $this->setTitle($title);
    40.         $this->setWeight($weight);
    41.         $this->setPrice($price);
    42.     }
    43.  
    44. }
    45.  
    46. class Planshet extends Product {
    47.    
    48. }
    49.  
    50. class Potato extends Product {
    51.  
    52.     function getPrice() {
    53.         if ($this->getWeight() > 10000) {
    54.             return parent::getPrice();
    55.         } else {
    56.             return $this->getPriceWithoutDiscount();
    57.         }
    58.     }
    59.  
    60. }
    61.  
    62. class Jacket extends Product {
    63.    
    64. }
    65.  
    66. $planshet = new Planshet('Планшет', 2000, 400);
    67. $potato = new Potato('Картошка', 700, 12000);
    68. $jacket = new Jacket('Куртка', 700, 2000);
    69.  
    70. var_dump($potato->getPrice());
    По условию задачи, у всех продуктов скидка 10%, поэтому в родительском классе определяем этот геттер getPrice с ценой где скидка уже учтена.(такое у тебя условие)
    Для продуктов где скидка может быть другая при определенных условиях переопределяешь getPrice как я уже сделал. а если этот порог не превзойден, вызывается метод определенный в родительском классе, для получения цены без скидки.

    Выще в коде, почти всегда я работаю со свойсвами через геттеры и сеттеры. Это поможет тебе в будущем, вдруг ты решить фильтровать какие либо значения, или же решишь проделать над ними кое-какие операции. Да и для доступа из дочерних классов они нужны.

    И свойства лучше всегда херачить в столбик, это удобно+ ты можешь документировать каждое свойство как полагается.
     
    Dimon2x нравится это.
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ну значит ещё дочитаешь, и начнёшь понимать, о чём я
     
  5. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    А тут же такие методы не нужны

    PHP:
    1. function setTitle($title) {
    2.         $this->title = $title;
    3.     }
    4.     function setPrice($price) {
    5.         $this->price = $price;
    6.     }
    7.     function setWeight($weight) {
    8.         $this->weight = $weight;
    9.     }
    В конструкторе же можно так прописать

    PHP:
    1. $this->title = $title;
    2. $this->price = $price;
    3. $this->weight = $weight;
     
  6. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    Можно. Но представь, что ты захочешь проделать какие либо операции с входными данными? Будешь это все городить в контсрукторе?
    Всегда работай с свойсвами через сеттеры и геттеры.
     
  7. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Я ещё сделал доставку на все продукты - 250 рублей, но если на продукт была скидка - 300 рублей

    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset:utf-8');
    3. abstract class Product{
    4.     private $title;
    5.     private $price;
    6.     private $weight;
    7.     private $discount = 10;
    8.     static $delivery = 250;
    9.    
    10.     public function incDelivery(){
    11.         return self::$delivery+50;
    12.     }
    13.    
    14.     public function getDiscount(){
    15.         return $this->discount;
    16.     }
    17.    
    18.     public function getPrice(){
    19.         return round($this->price - ($this->price * $this->getDiscount()/100));
    20.     }
    21.    
    22.     function getPriceWithoutDiscount() {
    23.         return $this->price;
    24.     }
    25.    
    26.     public function getTitle(){
    27.         return $this->title;
    28.     }
    29.    
    30.     public function getWeight(){
    31.         return $this->weight;
    32.     }
    33.    
    34.     public function dostavka(){
    35.         if($this->getPriceWithoutDiscount() > $this->getPrice()){
    36.             return $this->incDelivery();
    37.         }
    38.        
    39.         else{
    40.             return self::$delivery;
    41.         }
    42.     }
    43.     public function __construct($title, $price, $weight){
    44.         $this->title = $title;
    45.         $this->price = $price;
    46.         $this->weight = $weight;
    47.     }
    48. }
    49.  
    50. class Planshet extends Product{}
    51.  
    52. class Veggies extends Product{
    53.     function getPrice(){
    54.         if($this->getWeight() > 10000){
    55.             return parent::getPrice();
    56.         }
    57.         else{
    58.             return $this->getPriceWithoutDiscount();
    59.         }
    60.     }
    61. }
    62.  
    63. class Clothing extends Product{}
    64.  
    65. $planshet = new Planshet('Asus', 2000, 400);
    66. $veggies = new Veggies('Морковка', 700, 12000);
    67. $veggies2 = new Veggies('Лук', 700, 3000);
    68. $clothing = new Clothing('Куртка', 700, 2000);
    69.  
    70. ?>
    71. <!DOCTYPE html>
    72. <html>
    73.     <head>
    74.         <meta charset="utf-8">
    75.     </head>
    76.     <body>
    77.         <?php
    78.        
    79.             echo $planshet->getTitle() . ' цена без скидки ' . $planshet->getPriceWithoutDiscount() . ', со скидкой ' . $planshet->getPrice() . ', доставка ' . $planshet->dostavka();
    80.             echo '<br>';
    81.             echo $veggies->getTitle() . ' цена без скидки ' . $veggies->getPriceWithoutDiscount() . ', со скидкой ' . $veggies->getPrice() . ', доставка ' . $veggies->dostavka();
    82.             echo '<br>';
    83.             echo $veggies2->getTitle() . ' цена без скидки ' . $veggies2->getPriceWithoutDiscount() . ', со скидкой ' . $veggies2->getPrice() . ', доставка ' . $veggies2->dostavka();
    84.             echo '<br>';
    85.             echo $clothing->getTitle(). ' цена ' . $clothing->getPrice() . ', доставка ' .  $clothing::$delivery;
    86.         ?>
    87.     </body>
    88. </html>
     
  8. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    Не вижу где ты определяешь составила ли скидка 300р

    PHP:
    1. <?php
    2.  
    3. header('Content-Type: text/html; charset:utf-8');
    4.  
    5. abstract class Product {
    6.  
    7.     private $title;
    8.     private $price;
    9.     private $weight;
    10.     private $discount = 10;
    11.  
    12.     public function getDiscount() {
    13.         return $this->discount;
    14.     }
    15.  
    16.     public function getPrice() {
    17.         return round($this->price - ($this->price * $this->getDiscount() / 100));
    18.     }
    19.  
    20.     function getPriceWithoutDiscount() {
    21.         return $this->price;
    22.     }
    23.  
    24.     public function getTitle() {
    25.         return $this->title;
    26.     }
    27.  
    28.     public function getWeight() {
    29.         return $this->weight;
    30.     }
    31.  
    32.     public function costDelivery() {
    33.  
    34.         $discount = $this->getPriceWithoutDiscount() - $this->getPrice();
    35.         switch ($discount) {
    36.             case ($discount > 400):
    37.                 return 200;
    38.             case ($discount > 300):
    39.                 return 250;
    40.             default :
    41.                 return 300;
    42.         }
    43.     }
    44.  
    45.     public function __construct($title, $price, $weight) {
    46.         $this->title = $title;
    47.         $this->price = $price;
    48.         $this->weight = $weight;
    49.     }
    50.  
    51. }
    52.  
    53. class Planshet extends Product {
    54.    
    55. }
    56.  
    57. class Veggies extends Product {
    58.  
    59.     function getPrice() {
    60.         if ($this->getWeight() > 10000) {
    61.             return parent::getPrice();
    62.         } else {
    63.             return $this->getPriceWithoutDiscount();
    64.         }
    65.     }
    66.  
    67. }
    68.  
    69. class Clothing extends Product {
    70.    
    71. }
    72.  
    73. $planshet = new Planshet('Asus', 2000, 400);
    74. $veggies = new Veggies('Морковка', 10000, 12000);
    75. $veggies2 = new Veggies('Лук', 700, 3000);
    76. $clothing = new Clothing('Куртка', 700, 2000);
    77.  
    78. var_dump($veggies->costDelivery());

    Теперь самое время подумать о рефактоинге. :D
    Советую перечитать/прочитать о полиморфизм и композиции.
     
  9. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Теперь я правильно сделал абстрактный класс? Подскажите, что можно добавить?

    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset=utf8');
    3.  
    4. abstract class Animal{
    5.     public $name;
    6.    
    7.     public function __construct($name){
    8.         $this->name = $name;
    9.     }
    10.    
    11.     public function eat(){
    12.         echo 'ням-ням';
    13.     }
    14.    
    15.     abstract public function voice();
    16. }
    17.  
    18. class Cat extends Animal{
    19.     public function voice(){
    20.         return  'Мяу-мяу';
    21.     }
    22. }
    23.  
    24. class Dog extends Animal{
    25.     public function voice(){
    26.         return 'Гав-гав';
    27.     }
    28. }
    29.  
    30. $cat = new Cat('Мурка');
    31. $dog = new Dog('Мухтар');
    32.  
    33. echo $cat->name . ' говорит ' . $cat->voice();
    34. echo '<br>';
    35. echo $dog->name . ' говорит ' . $dog->voice();
     
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ну класс сделал, но так его использовать Ну скучно же. Этот код будет работать и без абстрактных классов. Ну хотя бы в массив их объедини и перебором. Или сделай функцию, которая принимает Animal, а передай её $dog и $cat, просто, чтоб почувствовать, зачем это всё нужно - все эти абстрактные классы и прочие приблуды
     
    Dimon2x нравится это.
  11. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    @mkramer так?

    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset=utf8');
    3.  
    4. abstract class Animal{
    5.     public $name;
    6.  
    7.     public function __construct($name){
    8.         $this->name = $name;
    9.     }
    10.  
    11.     public function eat(){
    12.         echo 'ням-ням';
    13.     }
    14.  
    15.     abstract public function voice();
    16. }
    17.  
    18. class Cat extends Animal{
    19.     public function voice(){
    20.         return  'Мяу-мяу';
    21.     }
    22. }
    23.  
    24. class Dog extends Animal{
    25.     public function voice(){
    26.         return 'Гав-гав';
    27.     }
    28. }
    29.  
    30. $cat = new Cat('Мурка');
    31. $dog = new Dog('Мухтар');
    32.  
    33. function createAnimal($animal, $name){
    34.     return new $animal($name);
    35. }
    36.  
    37. $cat = createAnimal('Cat', 'Мурка');
    38. echo $cat->name . ' говорит ' . $cat->voice();
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    та ни
    PHP:
    1. $animals = [];
    2. $animals[] = new Cat('Мурка');
    3. $animals[] = new Dog('Мухтар');
    4. function doSomeWork(Animal $creature) {
    5.   echo $creature->name . ' does ' . $creature->eat();
    6.   echo $creature->name . ' says ' . $creature->voice();
    7. }
    8.  
    9. foreach ($animals as $animal) {
    10.   doSomeWork($animal);
    11. }
     
    mkramer и Dimon2x нравится это.