Създаване на клас с Struct.new

  1. Как е по-добре всъщност да използваме Struct.new - наследявайки от анонимен Struct или присвоявайки анонимен Struct на константа и ако и двата начина са добри, то кога да използваме единия и кога другия? (и кой да използваме за задачите за домашно, като имаме предвид особеностите на двата варианта, както и на skeptic)

    В официалното решение на четвърта задача е използван следният подход:

    class Card < Struct.new(:rank, :suit)
      def to_s
        "#{rank.to_s.capitalize} of #{suit.to_s.capitalize}"
      end
    end
    

    В ruby-docs пише следното:

    If a block is given it will be evaluated in the context of StructClass, passing the created class as a parameter:

    Customer = Struct.new(:name, :address) do
      def greeting
        "Hello #{name}!"
      end
    end
    Customer.new("Dave", "123 Main").greeting  # => "Hello Dave!"
    

    This is the recommended way to customize a struct. Subclassing an anonymous struct creates an extra anonymous class that will never be used.

    Ако използваме втория начин обаче се сблъскваме със skeptic:

    constant is not in SCREAMING_SNAKE_CASE

    Тоест името на класа ни трябва да е само с главни букви, което пък противоречи на style guide-а.

    Още информация:

    • class Baba < Struct.new(:name, :age) е scope gate - тоест поведението на всичко, което пишем в класа ще е точно такова, каквото щеше да бъде, ако не използвахме < Struct.new - може би това е добре, ако искаме да се предпазим от неочаквани грешки
    • Baba = Struct.new(:name, :age) е по-добрата алтернатива според няколко източника, но като не забравяме как се търсят променливи и константи в този случай, тъй като този вариант не e scope gate

    Може ли някой по-разбиращ от мен да даде мнение по въпроса? (включително какво да използваме за домашното)

  2. Браво, това е много добро разбиване на плюсове и минуси за двата подхода. Сам си си отговорил на въпроса :)

    Знаеш каква е ползата от едното и каква е ползата от другото. Това означава, че можеш да решиш в контекста на конкретния случай, за който ти трябва.

    Skeptic се оплаква, защото гледа кода чисто синтактично и не знае това, което присвояваш на константа, дали е клас или нещо друго.

    Аз лично не смятам, че този допълнителен клас, който се създава, толкова надвишава минусите на това, че този блок вече не работи като другите дефиниции на класове. Особено в контекста на задачите тук. Много по-вероятно е да напишеш следното

    Card = Struct.new(:rank, :suit) do
      SUITS = [ ... ]
      RANKS = [ ... ]
    end
    

    и да изгубиш време в това да търсиш защо константите не са дефинирани на Card, отколкото да ти направи проблем допълнителният анонимен клас, от който наследяваш.

    Също, използването на Struct почти не се налага. Полезен е за малки класове, които представляват проста "опаковка" на няколко променливи. Не бих го използвал за клас със собствено поведение (различно от просто "контейнер" за неща) и повече от 2-3 метода. Особено ако не ми трябват повечето от методите, които дефинира (а те не са малко).

  3. Благодаря за отговора. :)

    Наистина често изобщо няма нужда от Struct, беше ми харесал като начин за създаване на класове, но не се бях замислил, че понякога не са нужни всички методи, идващи от него.

Трябва да сте влезли в системата, за да може да отговаряте на теми.