За последние 24 часа нас посетили 44511 программистов и 3000 роботов. Сейчас ищут 1314 программистов ...

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

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

  1. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Проверьте пожалуйста задание:

    1. Создайте базовый класс продукта.
    2. Создайте три любых типа продукта (класса), в разных категориях;
    3. Все продукты, кроме одного, имеют 10 процентную скидку и их цена должна выводиться с ней;
    4. Один тип продукта - имеет скидку только в том случае, если его вес больше 10 килограмм;

    Используйте примеси, интерфейсы или абстрактные классы в решении задачи.

    я не знаю, как правильно использовать абстрактные классы и интерфейсы.

    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset:utf-8');
    3.  
    4. abstract class Product{
    5.     public function __construct($title, $price, $weight){
    6.         $this->title = $title;
    7.         $this->price = $price;
    8.         $this->weight = $weight;
    9.     }
    10. }
    11.  
    12. class Planshet extends Product{
    13.     public $discount = 10;
    14.    
    15.     public function getPrice(){
    16.         if ($this->discount) {
    17.             return round($this->price - ($this->price * $this->discount/100));
    18.         }
    19.         else {
    20.             return $this->price;
    21.         }
    22.     }
    23. }
    24.  
    25. class Potato extends Planshet{
    26.     public function getPrice(){
    27.         if ($this->weight > 10000) {
    28.             return round($this->price - ($this->price * $this->discount/100));
    29.         }
    30.         else {
    31.             return $this->price;
    32.         }
    33.     }
    34. }
    35.  
    36. class Jacket extends Product{}
    37.  
    38. $planshet = new Planshet('Планшет', 2000, 400);
    39. $potato = new Potato('Картошка', 700, 4000);
    40. $potato2 = new Potato('Ещё картошка', 700, 12000);
    41. $jacket = new Jacket('Куртка', 6300, 2000);
    42.  
    43. ?>
    44. <!DOCTYPE html>
    45. <html>
    46.     <head>
    47.         <meta charset="utf-8">
    48.     </head>
    49.     <body>
    50.         <?php
    51.             echo $planshet->title . ' цена без скидки ' . $planshet->price . ', со скидкой ' . $planshet->getPrice();
    52.             echo '<br>';
    53.             echo $potato->title . ' цена без скидки ' . $potato->price . ', со скидкой ' . $potato->getPrice();
    54.             echo '<br>';
    55.             echo $potato2->title . ' цена без скидки ' . $potato2->price . ', со скидкой ' . $potato2->getPrice();
    56.             echo '<br>';
    57.             echo $jacket->title. ' цена ' . $jacket->price;
    58.         ?>
    59.     </body>
    60. </html>
     
  2. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Откуда задачи? С курсов? Или сам ищешь? Тебе объясняли что такое полиморфизм и нахрена это всё делается? По коду похоже, что нет. Тебе уже рекомендовали Зандстру - купи (скачай) и прочти, отпадёт большая часть вопросов.
     
  3. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    С курсов. Полиморфизм это когда унаследованные методы, работают по разному.
     
  4. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Угу. А зачем нужен полиморфизм? И зачем абстрактные классы?
     
  5. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Нужен что бы применять такой же метод у дочернего класса и можно слегка его переделать.

    В абстрактном классе просто пишется список методов, которые надо реализовать
     
  6. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ну да, почти. И где у вас первое? Где второе? Вообще, классическое определение: "Полиморфизм позволяет обращаться с объектами производных классов также как с объектами базового класса"
     
    #6 mkramer, 9 апр 2017
    Последнее редактирование: 9 апр 2017
  7. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    только, если они наследники.
     
  8. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Во, даже опечатку у меня заметил. Поправил. Так поправь теперь свой код :) Выдели общие операции, вынеси в абстрактный класс, сделай реализацию
     
  9. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Получается так

    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset:utf-8');
    3.  
    4. abstract class Product{
    5.     abstract function getPrice();
    6.    
    7.     public function __construct($title, $price, $weight){
    8.         $this->title = $title;
    9.         $this->price = $price;
    10.         $this->weight = $weight;
    11.     }
    12. }
    13.  
    14. class Planshet extends Product{
    15.     public $discount = 10;
    16.    
    17.     public function getPrice(){
    18.         if ($this->discount) {
    19.             return round($this->price - ($this->price * $this->discount/100));
    20.         }
    21.         else {
    22.             return $this->price;
    23.         }
    24.     }
    25. }
    26.  
    27. class Potato extends Planshet{
    28.     public function getPrice(){
    29.         if ($this->weight > 10000) {
    30.             return round($this->price - ($this->price * $this->discount/100));
    31.         }
    32.         else {
    33.             return $this->price;
    34.         }
    35.     }
    36. }
    37.  
    38. class Jacket extends Planshet{}
    39.  
    40. $planshet = new Planshet('Планшет', 2000, 400);
    41. $potato = new Potato('Картошка', 700, 4000);
    42. $potato2 = new Potato('Ещё картошка', 700, 12000);
    43. $jacket = new Jacket('Куртка', 6300, 2000);
    44.  
    45. ?>
    46. <!DOCTYPE html>
    47. <html>
    48.     <head>
    49.         <meta charset="utf-8">
    50.     </head>
    51.     <body>
    52.         <?php
    53.             echo $planshet->title . ' цена без скидки ' . $planshet->price . ', со скидкой ' . $planshet->getPrice();
    54.             echo '<br>';
    55.             echo $potato->title . ' цена без скидки ' . $potato->price . ', со скидкой ' . $potato->getPrice();
    56.             echo '<br>';
    57.             echo $potato2->title . ' цена без скидки ' . $potato2->price . ', со скидкой ' . $potato2->getPrice();
    58.             echo '<br>';
    59.             echo $jacket->title. ' цена ' . $jacket->price;
    60.         ?>
    61.     </body>
    62. </html>
     
  10. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ага, чуть больше похоже на правду. Но можно и лучше. Покажи мне, где ты тут обращаешься с объектом производного класса как с объектом базового? И поля закрой, что-ли :) Инкапсуляция, как-никак должна быть
     
  11. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Я вызываю конструктор
     
  12. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    @Dimon2x, в этом случе скиду стоит вынести в базовый абастранктный класс.
    И странно что класс Картошки наследует класс планшетов))
    --- Добавлено ---
    Вот для этого продукта можно будет переопределить метод скидки. На мой взгляд так логичнее.
     
  13. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Унаследованный конструктор - не полиморфизм. Ты вызываешь конкретный конструктор.
     
  14. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Вот такое получилось

    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset:utf-8');
    3.  
    4. abstract class Product{
    5.     abstract function setTitle($title);
    6.     abstract function getTitle();
    7.    
    8.     abstract function setPrice($price);
    9.     abstract function getPrice();
    10.    
    11.     abstract function getDiscount();
    12.    
    13.     protected $discount = 10;
    14.    
    15.     protected $title;
    16.     protected $price;
    17. }
    18.  
    19. class Planshet extends Product{
    20.  
    21.     public function setTitle($title){
    22.         $this->title = $title;
    23.     }
    24.    
    25.     public function getTitle(){
    26.         return $this->title;
    27.     }
    28.    
    29.     public function setPrice($price){
    30.         $this->price = $price;
    31.     }
    32.    
    33.     public function getPrice(){
    34.         return $this->price;
    35.     }
    36.    
    37.     public function getDiscount(){
    38.         if ($this->discount) {
    39.             return round($this->price - ($this->price * $this->discount/100));
    40.         }
    41.         else {
    42.             return $this->price;
    43.         }
    44.     }
    45. }
    46.  
    47. $planshet = new Planshet;
    48. $planshet->setTitle('Планшет');
    49. $planshet->setPrice('2000');
    50.  
    51. ?>
    52. <!DOCTYPE html>
    53. <html>
    54.     <head>
    55.         <meta charset="utf-8">
    56.     </head>
    57.     <body>
    58.         <?php
    59.             echo $planshet->getTitle() . ' цена без скидки ' . $planshet->getPrice() . ', со скидкой ' . $planshet->getDiscount();;
    60.             echo '<br>';
    61.         ?>
    62.     </body>
    63. </html>
     
  15. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Не-а, ты не врубаешься вообще, что к чему. Почитай книжку.

    Вот зачем ты абстрактными сделал методы, которые можно реализовать и на уровне базового класса. Ну порассуждай немного. Что меняется у разных типов продуктов? Алгоритм подсчёта скидки (кстати, ты и ТЗ не совсем верно понял, по видимому). У части продуктов скидка просто 10%, а у других - зависит от веса. Ну вот это и есть абстрактная функция. А цену можно посчитать как базовая цена минус скидка - это можно вполне, к примеру, разместить и в базовом классе, а также все эти геттеры-сеттеры. Вообще, тут конечно кое-что ещё напрашивается, о чём Зандстра пишет, но не буду сейчас так далеко заходить, чтоб не запутать.
     
  16. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Что я неправильно сделал? Как понять на уровне базового класса, это с помощью конструктора?
    --- Добавлено ---
    у них меняется цена и название
     
  17. mkramer

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

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

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Получается делать абстрактные методы, только для тех функций, у которых будет разная функциональность?
    Здесь это определение подходит только для скидки.

    А как написать свойства, у них же тоже содержимое у всех разное?
    --- Добавлено ---
    класс это шаблон, по которому делается объект
     
  19. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ну ты же писал конструкторы, сеттеры, геттеры.
    https://php.ru/forum/threads/abstraktnye-klassy-i-nasledovanie.62979/#post-511671 - вот тут ты был ближе всего к наилучшему решению задачи, которое ты можешь на данном уровне предложить. Но ты сделал полиморфорную функцию, а не использовал её преимущества никак :( Поэтому я тебе и задал вопрос, на который ты ответил неверно. Нет никакого преимущества от полиморфизма, если ты вручную создаёшь объекты, и потом у каждого дёргаешь по одному функцию. А вот если ты пишешь код, который думает, что он работает с Product, а передаёшь в него Planshet, и этот код правильно срабатывает для планшетов, хотя ты ни строчки в нём не менял - вот это использование полиморфизма.

    По поводу свойств. Свойства не у класса (если речь идёт не о статических свойствах), свойства у объектов. Смекаешь?
     
  20. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Так эти свойства же создаются по шаблону, которые указаны в классе.
     
  21. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ага. А значения указываются для каждого объекта. И ведь название и цена есть у любых товаров, а не только у планшетов или только у картофелин? Вот то, что у всех общее - это должно быть в базовом классе, то, что отличается - реализуется через полиморфизм.
     
  22. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Пропущено важное слово есть
    Вот то, что есть у всех общее - это должно быть в базовом классе.

    Без этого слова, получается, что общего ничего нету.
     
  23. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    Вот так сделал

    PHP:
    1. <?php
    2. header('Content-Type: text/html; charset:utf-8');
    3. abstract class Product{
    4.     public $title;
    5.     protected $price;
    6.     public $weight;
    7.    
    8.     private $discount = 10;
    9.    
    10.     public function getDiscount(){
    11.         return $this->discount;
    12.     }
    13.    
    14.     public function getPrice(){
    15.         return $this->price;
    16.     }
    17.    
    18.     protected function getPriceDiscount(){
    19.         if ($this->getDiscount()) {
    20.             return round($this->price - ($this->price * $this->getDiscount()/100));
    21.         }
    22.         else {
    23.             return $this->price;
    24.         }
    25.     }
    26.    
    27.     public function getFunGetPriceDiscount(){
    28.         return $this->getPriceDiscount();
    29.     }
    30.     public function __construct($title, $price, $weight){
    31.         $this->title = $title;
    32.         $this->price = $price;
    33.         $this->weight = $weight;
    34.     }
    35. }
    36.  
    37. class Planshet extends Product{}
    38.  
    39. class Potato extends Product{
    40.     function getFunGetPriceDiscount(){
    41.         if($this->weight > 10000){
    42.             return parent::getFunGetPriceDiscount();
    43.         }
    44.         else{
    45.             return $this->getPrice();
    46.         }
    47.     }
    48. }
    49.  
    50. class Jacket extends Product{}
    51.  
    52.  
    53. $planshet = new Planshet('Планшет', 2000, 400);
    54. $potato = new Potato('Картошка', 700, 12000);
    55. $jacket = new Jacket('Куртка', 700, 2000);
    56.  
    57. ?>
    58. <!DOCTYPE html>
    59. <html>
    60.     <head>
    61.         <meta charset="utf-8">
    62.     </head>
    63.     <body>
    64.         <?php
    65.        
    66.             echo $planshet->title . ' цена без скидки ' . $planshet->getPrice() . ', со скидкой ' . $planshet->getFunGetPriceDiscount();
    67.             echo '<br>';
    68.             echo $potato->title . ' цена без скидки ' . $potato->getPrice() . ', со скидкой ' . $potato->getFunGetPriceDiscount();
    69.             echo '<br>';
    70.             echo $jacket->title. ' цена ' . $jacket->getPrice();
    71.         ?>
    72.     </body>
    73. </html>
     
  24. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Не, чувак. Нифига ты не понимаешь полиморфизм. У тебя он всё только усложняет, а должен упрощать.
    PHP:
    1. <?php
    2. abstract class Product {
    3.     private $title, $price;
    4.      
    5.     public function __construct($t, $p)
    6.     {
    7.         $this->title = $t;
    8.         $this->price = $p;
    9.     }
    10.    
    11.     function getTitle() { return $this->title; }
    12.     function getPrice() { return $this->price * (1 - $this->getDiscount()); }
    13.    
    14.     abstract function getDiscount();
    15. }
    16.  
    17. class ProductWith10PercentDiscount extends Product {
    18.     function getDiscount()
    19.     {
    20.         return 0.1;
    21.     }
    22. }
    23.  
    24. class ProductWithWeightDiscount extends Product {
    25.     private $weight;
    26.    
    27.     public function __construct($t, $p, $w)
    28.     {
    29.         parent::__construct($t, $p);
    30.         $this->weight = $w;
    31.     }
    32.    
    33.     function getDiscount()
    34.     {
    35.         return $this->weight < 10 ? 0: 0.1;
    36.     }
    37. }
    38.  
    39.  
    40. $products = [
    41.     new ProductWith10PercentDiscount('Планшет', 2000),
    42.     new ProductWith10PercentDiscount("Фен", 1000),
    43.     new ProductWithWeightDiscount("Картошка", 15, 20),
    44.     new ProductWithWeightDiscount("Морковь", 15, 3)
    45. ];
    46.  
    47. foreach ($products as $p) {
    48.     echo $p->getTitle() . ' - ' . $p->getPrice() . '<br>';
    49. }
    Вот на что тут тебя всё наталкивали. Заметь,Product::getPrice() без понятия, как считается скидка, а вот производные классы указывают ей на это
     
    Dimon2x нравится это.
  25. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.211
    Симпатии:
    186
    но стало же лучше, чем было?
    --- Добавлено ---
    ну у тебя слишком крутой код для новичка
    --- Добавлено ---
    в каком месте у меня усложнил?
    --- Добавлено ---
    а почему вес не включили в базовый? Он же у всех есть
    --- Добавлено ---
    а зачем вы сделали 2 функции скидок, если можно одну?
    --- Добавлено ---
    А зачем название делать приватным?