Ricerca…


Sintassi

  • classe Sottoclasse <SuperClass

Rifattorizzare le classi esistenti per utilizzare l'ereditarietà

Diciamo che abbiamo due classi, Cat and Dog .

class Cat
  def eat
    die unless has_food?
    self.food_amount -= 1
    self.hungry = false
  end
  def sound
    puts "Meow"
  end
end

class Dog
  def eat
    die unless has_food?
    self.food_amount -= 1
    self.hungry = false
  end
  def sound
    puts "Woof"
  end
end

Il metodo eat è esattamente lo stesso in queste due classi. Mentre funziona, è difficile da mantenere. Il problema peggiorerà se non ci sono più animali con lo stesso eat metodo. L'ereditarietà può risolvere questo problema.

class Animal
  def eat
    die unless has_food?
    self.food_amount -= 1
    self.hungry = false
  end
  # No sound method
end

class Cat < Animal
  def sound
    puts "Meow"
  end
end

class Dog < Animal
  def sound
    puts "Woof"
  end
end

Abbiamo creato una nuova classe, Animal , e spostato il nostro metodo di eat in quella classe. Quindi, abbiamo fatto ereditare Cat e Dog da questa nuova superclasse comune. Ciò elimina la necessità di ripetere il codice

Eredità multipla

L'ereditarietà multipla è una caratteristica che consente ad una classe di ereditare da più classi (cioè più di un genitore). Ruby non supporta l'ereditarietà multipla. Supporta solo l'ereditarietà singola (cioè la classe può avere solo un genitore), ma puoi usare la composizione per costruire classi più complesse usando i moduli .

sottoclassi

L'ereditarietà consente alle classi di definire un comportamento specifico basato su una classe esistente.

class Animal
  def say_hello
    'Meep!'
  end

  def eat
    'Yumm!'
  end
end

class Dog < Animal
  def say_hello
    'Woof!'
  end
end

spot = Dog.new
spot.say_hello # 'Woof!'
spot.eat       # 'Yumm!'

In questo esempio:

  • Dog eredita da Animal , rendendolo una sottoclasse .
  • Dog guadagna sia il say_hello che eat metodi da Animal .
  • Dog sovrascrive il metodo say_hello con diverse funzionalità.

mixins

Le mixine sono un modo meraviglioso per ottenere qualcosa di simile all'ereditarietà multipla. Ci consente di ereditare o meglio includere i metodi definiti in un modulo in una classe. Questi metodi possono essere inclusi come metodi di istanza o classe. L'esempio seguente illustra questo design.

module SampleModule

  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods

    def method_static
      puts "This is a static method"
    end

  end

  def insta_method
    puts "This is an instance method"
  end

end

class SampleClass
  include SampleModule
end

sc = SampleClass.new

sc.insta_method

prints "This is an instance method"

sc.class.method_static

prints "This is a static method"

Cosa viene ereditato?

I metodi sono ereditati

class A
  def boo; p 'boo' end
end

class B < A; end

b = B.new
b.boo # => 'boo'

I metodi di classe sono ereditati

class A
  def self.boo; p 'boo' end
end

class B < A; end

p B.boo # => 'boo'

Le costanti sono ereditate

class A
  WOO = 1
end

class B < A; end

p B::WOO # => 1

Ma attenzione, possono essere ignorati:

class B
  WOO = WOO + 1
end

p B::WOO # => 2

Le variabili di istanza sono ereditate:

class A
  attr_accessor :ho
  def initialize
    @ho = 'haha'
  end
end

class B < A; end

b = B.new
p b.ho # => 'haha'

Attenzione, se si sostituiscono i metodi che inizializzano le variabili di istanza senza chiamare super , saranno nulli. Continuando dall'alto:

class C < A
  def initialize; end
 end

c = C.new
p c.ho    # => nil

Le variabili di istanza di classe non sono ereditate:

class A
    @foo = 'foo'
    class << self
        attr_accessor :foo
    end
end

class B < A; end

p B.foo # => nil

# The accessor is inherited, since it is a class method
#
B.foo = 'fob' # possible

Le variabili di classe non sono realmente ereditate

Sono condivisi tra la classe base e tutte le sottoclassi come 1 variabile:

class A
    @@foo = 0
    def initialize
        @@foo  += 1 
        p @@foo
    end
end

class B < A;end

a = A.new # => 1
b = B.new # => 2

Quindi continuando dall'alto:

class C < A
  def initialize
    @@foo = -10
    p @@foo
  end
end

a = C.new # => -10
b = B.new # => -9


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow