Невозможно включить класс в другой класс в Ruby: неинициализированная константа (NameError)

Допустим, у меня есть три класса, каждый из которых определяется в своем собственном файле. например ClassA в ClassA.rb и т.д...

class ClassA
  def initialize
  end

  def printClassA
    puts "This is class A"
  end
end

class ClassB
  def initialize
  end

  def printClassB
    puts "This is class B"
  end
end

class ClassC

  def initialize
  end

  def bothClasses
    a = ClassA.new
    b = ClassB.new
    a.printClassA
    b.printClassB
  end
end

Как видите, для правильной работы ClassC нужны два других класса. Я предполагаю, что должен быть способ импортировать/включать/загружать два других класса в ClassC.

Я новичок в Ruby, и я пробовал каждую перестановку load/include/require, и я не могу понять, как заставить это работать.

Обычно я просто получаю:

classc.rb:2:in `<class:ClassC>': uninitialized constant ClassC::ClassA (NameError)
    from classc.rb:1:in `<main>'

Или синтаксическая ошибка с моими операторами import/include/require.

При использовании Windows 7, Ruby 1.9.2, RadRails все файлы находятся в одном проекте и исходной папке.

Извините, если этот вопрос похож на некоторые другие вопросы здесь, но большинство ответов на разрешение «неинициализированной константы» заключается в том, чтобы «просто потребовать файл». Я пробовал, и это не работает.


person user604886    schedule 06.02.2011    source источник


Ответы (2)


Я думаю, ваша проблема в том, что $:, переменная, которая контролирует, где require ищет файлы, больше не включает текущий каталог в Ruby 1.9.2 и выше (по соображениям безопасности). Чтобы сообщить Ruby, где искать файл, вам нужно выполнить одно из следующих действий:

require_relative 'ClassA' # which looks in the same directory as the file where the method is called

# or #

require './ClassA' # which looks in the current working directory
person Chuck    schedule 06.02.2011

Если я храню все в одном файле и добавляю две строки в ваш код, он отлично работает на 1.9.2:

class ClassA
  def initialize
  end

  def printClassA
    puts "This is class A"
  end
end

class ClassB
  def initialize
  end

  def printClassB
    puts "This is class B"
  end
end

class ClassC

  def initialize
  end

  def bothClasses
    a = ClassA.new
    b = ClassB.new
    a.printClassA
    b.printClassB
  end
end

c = ClassC.new
c.bothClasses
# >> This is class A
# >> This is class B

Это говорит мне, что код в порядке, проблема в том, что вы включили файлы.

Я разделил первые два класса на отдельные файлы, "classa.rb" и "classb.rb" соответственно, а затем изменил файл следующим образом:

require_relative './classa'
require_relative './classb'

class ClassC

  def initialize
  end

  def bothClasses
    a = ClassA.new
    b = ClassB.new
    a.printClassA
    b.printClassB
  end
end

c = ClassC.new
c.bothClasses

После его запуска я получил те же результаты, показывающие, что он работал правильно.

Я использую './path/to/file', потому что он самодокументируется там, где я ищу, но 'path/to/file' или, в данном случае, 'classa' тоже подойдет.

Затем я переключился на Ruby 1.8.7, изменил строки require_relative на require и снова сохранил файл. Запуск из командной строки снова работал корректно:

require './classa'
require './classb'

class ClassC

  def initialize
  end

  def bothClasses
    a = ClassA.new
    b = ClassB.new
    a.printClassA
    b.printClassB
  end
end

c = ClassC.new
c.bothClasses

Из соображений безопасности Ruby 1.9+ удалил текущий каталог '.' из списка каталогов, которые искал require. Поскольку они знали, что мы выследим их с вилами и факелами, они добавили команду require_relative, которая позволяет искать в текущем каталоге и ниже.

person the Tin Man    schedule 06.02.2011
comment
Вы поместили их в три отдельных файла? Это будет работать нормально, если все они находятся в одном и том же файле .rb. - person user604886; 06.02.2011