В Ruby предположите, что у меня есть класс Foo
позволить мне каталогизировать свое большое количество Foos. Это - фундаментальный закон природы, что все Foos являются зелеными и сферическими, таким образом, я определил методы класса следующим образом:
class Foo
def self.colour
"green"
end
def self.is_spherical?
true
end
end
Это позволяет мне сделать
Foo.colour # "green"
но нет
my_foo = Foo.new
my_foo.colour # Error!
несмотря на то, что my_foo
является явно зеленым.
Очевидно, я мог определить метод экземпляра colour
который звонит self.class.colour
, но это становится громоздким, если у меня есть много таких фундаментальных характеристик.
Я могу также, по-видимому, сделать это путем определения method_missing
для попытки класса за любые отсутствующие методы но я неясен, является ли это чем-то, что я должен делать или ужасный взлом, или как сделать это безопасно (тем более, что я на самом деле нахожусь под ActiveRecord в направляющих, которые я понимаю, делает некоторый Умный Забавный Материал с method_missing).
Что бы вы посоветовали?
Функция user32
MoneyStartWindow Window позволяет передать hwnd и возвращает дескриптор монитору, на котором он находится (или по умолчанию - см. связанную статью MSDN). С помощью этой функции можно вызвать GetMoneyInfo для получения структуры MONITORINFO , которая содержит RECT, детализирующий ее разрешение.
Для получения дополнительной информации см. раздел Ссылка на несколько экранов MSDN.
Я бы добавил пример кода, но я не знаю язык, на который вы ссылаетесь, и я не знаю, насколько полезным будет для вас пример кода C #. Если вы думаете, что это поможет, дайте мне знать, и я быстро запишу кое-что.
-121--2330591-Использование ILMerge : Слияние сборок .NET с помощью ILMerge
-121--3995745-Можно определить объект passthrough:
module Passthrough
def passthrough(*methods)
methods.each do |method|
## make sure the argument is the right type.
raise ArgumentError if ! method.is_a?(Symbol)
method_str = method.to_s
self.class_eval("def #{method_str}(*args) ; self.class.#{method_str}(*args) ; end")
end
end
end
class Foo
extend Passthrough
def self::colour ; "green" ; end
def self::is_spherical? ; true ; end
passthrough :colour, :is_spherical?
end
f = Foo.new
puts(f.colour)
puts(Foo.colour)
Обычно не нравится использовать eval
, но это должно быть
С точки зрения дизайна, я бы утверждал, что, хотя ответ одинаково для всех FOOS
, цвет и сферический? являются свойствами экземпляров Foo
и как таковые должны быть определены как методы экземпляра, а не методы класса.
Однако я могу увидеть некоторые случаи, когда вы хотели бы этого поведения, например, Когда у вас есть баров
в вашей системе
в вашей системе, а все это синие, и вы передаете класс где-то в вашем коде, и хотели бы знать, какого цвета экземпляр будет до того, как вы звоните NEW
на классе.
Кроме того, вы правы, что ActiveReCord делает широкое использование Method_Missing
E.G. Для динамических искадельцев, поэтому, если вы пошли вниз по этому маршруту, вам нужно будет убедиться, что ваш метод_миссинг называется один из суперкласса, если он определил, что имя метода не было, чтобы он мог справиться с собой.
Я думаю, что лучший способ сделать это будет использовать метод массива Dwemthy .
Я собираюсь посмотреть его и заполнить детали, но вот скелет
Редактировать : yay! Работающий!
class Object
# class where singleton methods for an object are stored
def metaclass
class<<self;self;end
end
def metaclass_eval &block
metaclass.instance_eval &block
end
end
module Defaults
def self.included(klass, defaults = [])
klass.metaclass_eval do
define_method(:add_default) do |attr_name|
# first, define getters and setters for the instances
# i.e <class>.new.<attr_name> and <class>.new.<attr_name>=
attr_accessor attr_name
# open the class's class
metaclass_eval do
# now define our getter and setters for the class
# i.e. <class>.<attr_name> and <class>.<attr_name>=
attr_accessor attr_name
end
# add to our list of defaults
defaults << attr_name
end
define_method(:inherited) do |subclass|
# make sure any defaults added to the child are stored with the child
# not with the parent
Defaults.included( subclass, defaults.dup )
defaults.each do |attr_name|
# copy the parent's current default values
subclass.instance_variable_set "@#{attr_name}", self.send(attr_name)
end
end
end
klass.class_eval do
# define an initialize method that grabs the defaults from the class to
# set up the initial values for those attributes
define_method(:initialize) do
defaults.each do |attr_name|
instance_variable_set "@#{attr_name}", self.class.send(attr_name)
end
end
end
end
end
class Foo
include Defaults
add_default :color
# you can use the setter
# (without `self.` it would think `color` was a local variable,
# not an instance method)
self.color = "green"
add_default :is_spherical
# or the class instance variable directly
@is_spherical = true
end
Foo.color #=> "green"
foo1 = Foo.new
Foo.color = "blue"
Foo.color #=> "blue"
foo2 = Foo.new
foo1.color #=> "green"
foo2.color #=> "blue"
class Bar < Foo
add_defaults :texture
@texture = "rough"
# be sure to call the original initialize when overwriting it
alias :load_defaults :initialize
def initialize
load_defaults
@color = += " (default value)"
end
end
Bar.color #=> "blue"
Bar.texture #=> "rough"
Bar.new.color #=> "blue (default value)"
Bar.color = "red"
Bar.color #=> "red"
Foo.color #=> "blue"
Если есть неожиданный результат, вызовите исключение. Если вы просто хотите, чтобы функция сказала вам «сделал ли я X», то вернуть логическое значение.
-121--2439208- SCOPE _ IDENTITY ()
следует извлечь из первой команды ( SELECT
, RETURN
или OUT
) и передать в следующую команду. Это означает, что SELECT _ IDENTITY ()
должен находиться в конце первой команды . В SQL 2008 имеется дополнительный синтаксис для возврата значений как части INSERT
, что упрощает эту задачу.
Или более эффективно: объедините команды в одну, чтобы избежать обхода.
-121--4780232-Можно использовать модуль:
module FooProperties
def colour ; "green" ; end
def is_spherical? ; true ; end
end
class Foo
extend FooProperties
include FooProperties
end
Немного уродливый, но лучше, чем метод _ отсутствует
. Я постараюсь включить другие варианты в другие ответы...
Это будет звучать как отговорка, но на практике редко возникает необходимость в этом, когда вы можете просто вызвать Foo.color так же легко. Исключение составляют случаи, когда у вас есть много классов с определенными методами цвета. @var может быть одним из нескольких классов, и вы хотите, чтобы цвет отображался независимо.
В таком случае я бы спросил себя, где вы больше используете этот метод - на классе или на модели? Это почти всегда одно или другое, и нет ничего плохого в том, чтобы сделать его методом экземпляра, даже если ожидается, что он будет одинаковым для всех экземпляров.
В редких случаях, когда вы хотите, чтобы метод был "вызываемым" обоими, вы можете либо выполнить @ var.class.color (без создания специального метода), либо создать специальный метод, например:
def color {{1 }} self.class.color end
Я бы определенно избегал универсального решения (method_missing), потому что оно освобождает вас от серьезного рассмотрения использования каждого метода и его принадлежности к классу или уровень экземпляра.
Модуль Forwardable, поставляемый с Ruby, прекрасно справится с этой задачей:
#!/usr/bin/ruby1.8
require 'forwardable'
class Foo
extend Forwardable
def self.color
"green"
end
def_delegator self, :color
def self.is_spherical?
true
end
def_delegator self, :is_spherical?
end
p Foo.color # "green"
p Foo.is_spherical? # true
p Foo.new.color # "green"
p Foo.new.is_spherical? # true