2015-03-07 3 views
1

Ruby core library Сложный класс можно назвать так, как если бы он был методом.Как Ruby `Complex` вызывается как метод, когда он является классом?

Complex.class #=> Class 
Complex(1, 2) #=> (1+2i) 

Как это возможно?

Я мог бы переопределить [], но не ().

class MyComplex 
    def self.[](real, image) # This works. 
    "#{real} + #{image}i" 
    end 
    def self.()(real, image) # This is not allowed in ruby. 
    "#{real} + #{image}i" 
    end 
end 

MyComplex[1,2] #=> "1+2i" 
MyComplex(1,2) # I want this working like Complex class. 
+3

См. Http://stackoverflow.com/q/28845222/477037 – Stefan

ответ

2

Ну, тогда вам нужно поместить инициализацию внутри Kernel модуля.

module Kernel 
    def MyComplex 
    MyComplex.new 
    end 
end 

Рубин ядро ​​Lib определяется #Complex() внутри Kernel модели. Если определить его внутри Kernel модуля, то вы можете воспользоваться преимуществами этих методов с использованием подмешать, как показано ниже:

class MyComplex 
    def initialize(real, image) 
    "#{real} + #{image}i" 
    end 
end 

module Kernel 
    def MyComplex(real, image) 
    MyComplex.new real, image 
    end 
end 

class Klass < BasicObject 
    include ::Kernel 

    def create_object a, b 
    MyComplex(a, b) 
    end 
end 

p Klass.new.create_object 1, 2 
# >> #<MyComplex:0xa01b008> 

Если определить его в верхнем уровне, этот метод становится частным методом класс Object, то у вас нет простого способа повторного использования метода:

def MyComplex(real, image) 
    MyComplex.new real, image 
end 

class Klass < BasicObject 
    def create_object a, b 
    MyComplex(a, b) 
    end 
end 

p Klass.new.create_object 1, 2 
# `create_object': undefined method `MyComplex' 
+0

Но Ruby's Complex - это класс, а не метод. Я хочу знать, как Complex может вести себя как метод, когда он является классом. –

+2

@JecholLee: синтаксический анализатор указывает на различное использование константы 'Complex' (как ссылку на класс или метод), а язык допускает это двойное использование. –

+0

", то вам нужно поставить инициализацию внутри модуля« Ядро »- что? Это нонсенс. Пожалуйста, см. Ответ @NeilSlater, это правильно. – mudasobwa

2

это на самом деле удивительно просто, и AFAIK это как Руби и Ruby-библиотека сделать это:

class MyComplex 
    def self.[](real, image) # This works. 
    "#{real} + #{image}i" 
    end 
end 

def MyComplex(real, image) 
    "#{real} + #{image}i" 
end 

MyComplex[1,2] # "1+2i" 
MyComplex(1,2) # "1+2i" 
+0

Действительно полезно. Благодарю. –

+0

@ mudasobwa Почему вы заставляете OP? Вы уверены, ни у кого не будет ответа? –

+0

@Neil Slater Я оценил ваш ответ, но мне просто нужно больше времени, чтобы другие могли ответить. –

3

Ваше предположение неверно. Complex в Complex.class является классом, а Complex в Complex(1, 2) - это метод, определенный на Kernel. Это разные вещи.

+0

Я понял. Благодарю. –

+0

Но, по-видимому, комплекс задан в Object. 'Kernel.constants.include? : Complex # false', 'Object.constants.include? : Complex # true'. –

+0

Я не понимаю актуальность вашего кода в комментарии. Ваш код проверяет константы, а не методы. 'method (: Complex) .owner # => Kernel'. – sawa

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