Ruby: области видимости

Модератор: Модераторы разделов

Аватара пользователя
Иван Шихалев
Сообщения: 167
Статус: принципиальный дилетант
ОС: Gentoo Linux

Ruby: области видимости

Сообщение Иван Шихалев »

Имеется примерно такая конструкция:

Код: Выделить всё

module Test

  DATA = "Dtata"

  @data = "Data"
  class << self
    def data
      @data
    end
  end

  class TestC
    def testData
      puts DATA
    end
  end

end

Это работает, т.е. к константе модуля из метода экземпляра класса обратиться можно. А вот как можно обратиться к методу модуля, в данном примере — 'data', кроме как 'Test.data'? Да, если метод 'data' определить без 'class << self', это ничего не изменит — внутри класса он не виден.

И еще вопрос: существует ли хороший русскоязычный форум по Ruby?
Иван Шихалев
shikhalev.org
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: Ruby: области видимости

Сообщение KiWi »

Иван Шихалев писал(а):
30.07.2010 00:28
Имеется примерно такая конструкция:

Код: Выделить всё

module Test

  DATA = "Dtata"

  @data = "Data"
  class << self
    def data
      @data
    end
  end

  class TestC
    def testData
      puts DATA
    end
  end

end

Это работает, т.е. к константе модуля из метода экземпляра класса обратиться можно. А вот как можно обратиться к методу модуля, в данном примере — 'data', кроме как 'Test.data'? Да, если метод 'data' определить без 'class << self', это ничего не изменит — внутри класса он не виден.

И еще вопрос: существует ли хороший русскоязычный форум по Ruby?

Метод data в этом примере -- это метод модуля, который имеет доступ к локальной переменной модуля @data.
@data -- локальная переменная экземпляра класса.

Чтобы обратиться к TestC нужно сделать include Test(это так называемый mixin). После этого метод data также добавляется в тот класс, в котором сделан include. И идёт попытка уже к локальной переменной этого класса.

Как-то коряво написано... Лучше на примере для класса:

Код: Выделить всё

class Test
    @data = "123"

    def Test.data
        puts @data
    end

    def data
        puts @data
    end
end

Test.data
Test.new.data


Ну или для модуля:

Код: Выделить всё

module Test
    @data = "123"

    def Test.data
        puts "method: " + @data
    end

    def data
        puts "mixin: " + @data
    end
end

@data = "456"
Test.data
include Test
data
Спасибо сказали:
Аватара пользователя
Иван Шихалев
Сообщения: 167
Статус: принципиальный дилетант
ОС: Gentoo Linux

Re: Ruby: области видимости

Сообщение Иван Шихалев »

Это все понятно. В данном случае модуль нужен в качестве namespace в первую очередь. Просто хотелось бы понять, как определяемые в его пределах классы могут обращаться к другим его элементам. Ведь ни в них них ни его константы, ни другие внутренние классы, не требуют при использовании префикса 'Test::', а к методам получается обратиться только через 'Test.method'... Не очень понятно, каково общее правило.
Иван Шихалев
shikhalev.org
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: Ruby: области видимости

Сообщение KiWi »

Иван Шихалев писал(а):
30.07.2010 03:36
Это все понятно. В данном случае модуль нужен в качестве namespace в первую очередь. Просто хотелось бы понять, как определяемые в его пределах классы могут обращаться к другим его элементам. Ведь ни в них них ни его константы, ни другие внутренние классы, не требуют при использовании префикса 'Test::', а к методам получается обратиться только через 'Test.method'... Не очень понятно, каково общее правило.

Бр...

Есть метод модуля, который доступен по Test.method.

Есть mixin, для которого нужен include.

Это РАЗНЫЕ вещи.

module != namespace
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Ruby: области видимости

Сообщение diesel »

Иван Шихалев писал(а):
30.07.2010 03:36
Это все понятно. В данном случае модуль нужен в качестве namespace в первую очередь. Просто хотелось бы понять, как определяемые в его пределах классы могут обращаться к другим его элементам. Ведь ни в них них ни его константы, ни другие внутренние классы, не требуют при использовании префикса 'Test::', а к методам получается обратиться только через 'Test.method'... Не очень понятно, каково общее правило.

Элементы внутри модуля: константы, классы, переменные, функции итд, видны всему модулю. То есть в каком-нить classA, вы можете сделать b = classB.new() и создать экземпляр класса B, определенного в этом же модуле. методы класса самостоятельными элементами модуля, которые доступны всем и каждому, не являются. то есть или определяйте просто функции внутри модуля, или проявите к ним должное уважение )
Спасибо сказали:
Аватара пользователя
Иван Шихалев
Сообщения: 167
Статус: принципиальный дилетант
ОС: Gentoo Linux

Re: Ruby: области видимости

Сообщение Иван Шихалев »

Что значит «функции внутри модуля»? Я обявляю внутри модуля

Код: Выделить всё

def aaaaa
  puts 'AAAAAAAAAAAAAA'
end

Но потом внутри класса, описанного так же внутри модуля, вызвать не могу. О чем, впрочем, писал в первом сообщении. Или есть какие-то особые функции, определяемые иначе и модулями не являющиеся?

KiWi писал(а):
30.07.2010 11:23
module != namespace

(Programming Ruby, Second Edition) писал(а):Modules are a way of grouping together methods, classes, and constants. Modules give
you two major benefits.
1. Modules provide a namespace and prevent name clashes.
2. Modules implement the mixin facility.
Иван Шихалев
shikhalev.org
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Ruby: области видимости

Сообщение diesel »

Иван Шихалев писал(а):
30.07.2010 14:02
Что значит «функции внутри модуля»? Я обявляю внутри модуля

пардон.
или без модуля, и тогда все просто:

Код: Выделить всё

diesel@:~$ cat test.rb

        def extfunction
                puts "Function in module"
        end

        class A
                def a_some_func()
                        puts "inside A"
                        extfunction()
                end
        end

        a = A.new()
        a.a_some_func()


diesel@:~$ ruby test.rb
inside A
Function in module


Или если модуль:

Код: Выделить всё

diesel@:~$ cat test.rb
module Test

        def extfunction
                puts "Function in module"
        end

        class A
                include Test
                def a_some_func()
                        puts "inside A"
                        extfunction()
                end
        end

        a = A.new()
        a.a_some_func()
end

diesel@:~$ ruby test.rb
inside A
Function in module



или:

Код: Выделить всё

diesel@:~$ cat test.rb
module Test

        def extfunction
                puts "Function in module"
        end
        module_function :extfunction

        class A
                def a_some_func()
                        puts "inside A"
                        Test.extfunction()
                end
        end

        a = A.new()
        a.a_some_func()
end


diesel@:~$ ruby test.rb
inside A
Function in module
Спасибо сказали:
Аватара пользователя
Иван Шихалев
Сообщения: 167
Статус: принципиальный дилетант
ОС: Gentoo Linux

Re: Ruby: области видимости

Сообщение Иван Шихалев »

Интересно... А что делает

Код: Выделить всё

   module_function :extfunction

просто определяет ее же как

Код: Выделить всё

def Test.extfunction

?
Иван Шихалев
shikhalev.org
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Ruby: области видимости

Сообщение diesel »

Иван Шихалев писал(а):
30.07.2010 15:29
Интересно... А что делает

Код: Выделить всё

   module_function :extfunction

просто определяет ее же как

Код: Выделить всё

def Test.extfunction

?


Creates module functions for the named methods. These functions may be called with the module as a receiver, and also become available as instance methods to classes that mix in the module. Module functions are copies of the original, and so may be changed independently. The instance-method versions are made private. If used with no arguments, subsequently defined methods become module functions.

http://ruby-doc.org/core/classes/Module.html#M001642
Спасибо сказали: