Ruby def и instance_eval против class_eval

Вместо того, чтобы использовать интервал. TryParse () или Преобразовывают. ToInt32 (), мне нравится иметь статическую целочисленную функцию парсинга, которая возвращает пустой указатель, когда это не может проанализировать. Тогда я могу использовать?? и тернарный оператор вместе, чтобы более ясно гарантировать мое объявление и инициализацию все сделан на одной строке легким для понимания способом.

public static class Parser {
    public static int? ParseInt(string s) {
        int result;
        bool parsed = int.TryParse(s, out result);
        if (parsed) return result;
        else return null;
    }
    // ...
}

Этого также хорошо постараться не копировать левую сторону присвоения, но еще лучше стараться не копировать долгие запросы к правой стороне присвоения, такие как база данных звонит в следующий пример. Вместо ужасного, если тогда деревья (с которым я часто сталкиваюсь):

int x = 0;
YourDatabaseResultSet data = new YourDatabaseResultSet();
if (cond1)
    if (int.TryParse(x_input, x)){
        data = YourDatabaseAccessMethod("my_proc_name", 2, x);
    }
    else{
        x = -1;
        // do something to report "Can't Parse"    
    }
}
else {
    x = y;
    data = YourDatabaseAccessMethod("my_proc_name", 
       new SqlParameter("@param1", 2),
       new SqlParameter("@param2", x));
}

можно сделать:

int x = cond1 ? (Parser.ParseInt(x_input) ?? -1) : y;
if (x >= 0)  data = YourDatabaseAccessMethod("my_proc_name", 
    new SqlParameter("@param1", 2),
    new SqlParameter("@param2", x));

Намного более чистый и легче понять

29
задан Jo Liss 10 December 2010 в 13:12
поделиться

1 ответ

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

Следуя вашим примерам:

class A
  # defs here go to A
  puts self  # => A
  class << self
     #defs here go to A's eigenclass
  end
end

A.class_eval do
  #defs here go to A
end

A.instance_eval do
  #defs here go to A's eigenclass     
end

s = "Hello World"

class << s
  #defs here go to s's eigenclass
end

Вот часть главы, в которой говорится о проблеме, и довольно ясно о поведении

class_eval и instance_eval оба устанавливают self для продолжительность блока. Однако они отличаются тем, как они настраивают среду для определения метода. class_eval настраивает вещи так, как если бы вы были в теле определения класса, поэтому определения методов будут определять методы экземпляра. Напротив, вызов instance_eval для класса действует так, как если бы вы работали внутри синглтон-класса self. Поэтому любые методы, которые вы определите, станут методами класса.

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

Некоторое уместное прочтение:

Ruby: определения методов instance_eval и class_eval

Глава 4 этой самой выдающейся серии

34
ответ дан 28 November 2019 в 01:54
поделиться