2015-07-09 3 views
4

Я пытаюсь понять систему наследования в Ruby. Это мой код:Класс и наследование

class Man 
    attr_accessor :name 

    def initialize(name = "Foo") 
    @name = name 
    end 
end 

class User < Man 
    attr_accessor :mail 

    def initialize(mail = "bar") 
    super 
    @mail = mail 
    end 
end 

И это мой тест:

man = Man.new 
man 
=> #<Man:0x007fb68da4a768 @name="Foo"> 

user = User.new 
user 
=> #<User:0x007fb68da442c8 @name="bar", @mail="bar"> 

Я не понимаю, почему @name пользователя не "Foo"! Нормальный, это должно быть потому, что это аргумент по умолчанию в методе инициализации человека, нет?

Благодарим за помощь!

ответ

3

super (без списка аргументов) вызывает тот же метод суперкласса с теми же аргументами, которые были переданы в случае, если вы хотите, чтобы в явном виде проход no аргументы, вы must используйте пустой список аргументов: super().

Помните: super не является вызовом метода, это ключевое слово и ключевые слова не должны следовать нормальным правилам оценки вызова метода. Это одно из этих различий. Для вызова метода foo и foo() эквивалентны, они оба не передают никаких аргументов. Для super, is a разница: super() не передается аргументов, superфорварды аргументы.

Теперь вот еще один поворот: на самом деле, вы не делаете, передайте любые аргументы initialize, так как они передаются ... или вы? Ну, оказывается, для вызова super аргументы по умолчанию для необязательных параметров обрабатываются так, как если бы они были переданы явно.

+0

Большое спасибо за ваш полный ответ! Я думал, что это такой метод, как другой! – Wizix

2

super без аргументов является ярлыком для передачи тех же аргументов, которые были переданы в текущий исполняемый метод. В вашем примере «бар» был передан неявно суперклассу (поэтому вы получаете для них «бар»).

Необязательное решение, чтобы избежать путаницы:.

class User < Man 
    attr_accessor :mail 

    def initialize(name = "foo", mail = "bar") 
    super(name) 
    @mail = mail 
    end 
end 
+0

Почему вы определяете два параметра? вы можете вызывать 'super()' без параграммы, и вы получаете значение по умолчанию из класса родителя –

+0

@LukasBaliak, это правильно. Но что, если мы хотим определить их как отличные от значений по умолчанию? Преимущество этого варианта. – TechWisdom

+0

это правильно, но он хочет понять, почему имя было определено как почта. Ofc вы можете использовать это для «переопределения» имени var. После 'super()' вы можете использовать 'user.name =" новое имя "' –

0

Вы вызываете класс User с помощью одного параметра, а внутри инициализируемого вы вызываете родительский класс с тем же паррамером bcs. вы используете super вот так.

Если вы звоните super(), вы не отправляете парраметры bcs, которые вы вызываете, родительский начальный метод без парраметров.

как этот

class Man 
    attr_accessor :name 

    def initialize(name = "Foo") 
    @name = name 
    end 
end 

class User < Man 
    attr_accessor :mail 

    def initialize(mail = "bar") 
    super() 
    @mail = mail 
    end 
end 

Man.new 
# => #<Man:0x52a7e380 @name="Foo"> 
User.new 
# => #<User:0x11777eb0 @mail="bar", @name="Foo"> 
0

Просто попробуйте это, и это будет работать для вас:

class Man 
    attr_accessor :name 

    def initialize(name = "Foo") 
    @name = name 
    end 
end 

class User < Man 
    attr_accessor :mail 

    def initialize(mail = "bar") 
    super() 
    @mail = mail 
    end 
end 

man = Man.new 
puts man.name #> Foo 
user = User.new 
puts user.name #> Foo 
0

супер без аргументов, вызывает инициализатор суперкласса с теми же аргументами, что называли себя. Вы можете видеть это, потому что имя имеет то же значение, что и почта.

То, что вы хотите сделать, это:

def initialize(mail = "bar") 
    super() 
    @mail = mail 
end 

С помощью скобок, по умолчанию другой инициализатора используется, как вы намеревались.

Смежные вопросы