Ruby on Rails에서 추상 클래스를 시뮬레이션하고 싶습니다. 나는. 다른 사람이 Abstract.new
에 전화를하면 예외가 발생하지만 Child.new
(Child < Abstract
)으로 전화 할 수 있어야합니다.Ruby에서 추상 클래스 시뮬레이션 (레일즈)
어떻게 하시겠습니까? new
및 initialize
덮어 쓰기가 작동하지 않습니다.
Ruby on Rails에서 추상 클래스를 시뮬레이션하고 싶습니다. 나는. 다른 사람이 Abstract.new
에 전화를하면 예외가 발생하지만 Child.new
(Child < Abstract
)으로 전화 할 수 있어야합니다.Ruby에서 추상 클래스 시뮬레이션 (레일즈)
어떻게 하시겠습니까? new
및 initialize
덮어 쓰기가 작동하지 않습니다.
왜이 작업을 수행 하시겠습니까? 추상/인터페이스 클래스의 핵심은 강력하게 유형화 된 언어를 동적 패러다임으로 해킹하는 것입니다. 클래스를 서명에 적합하게 만들려면 원래 클래스에 따라 메소드의 이름을 지정하거나 파사드를 만들고 플러그를 꽂으십시오. 컴파일러를 속이려 고하지 않아도됩니다.
def my_printer obj
p obj.name
end
그래서 나는
class person
attr_accessor :name
def initialize
@name = "Person"
end
end
class Employee
attr_accessor :name
def initialize
@name = "Employee"
@wage = 23
end
end
그래서 아무 것도 모두이 이름을 인쇄이
my_printer Person.new
my_printer Employee.new
중 하나를 사용하여 우리의 프린터 메소드를 호출에서 우리를 멈추지 이름 속성을 어떤 객체와 인터페이스를 정의 차질없이 : D
기본적으로 이것은 주석이 아니라 대답입니다. – apneadiving
그런데 좋은 코멘트이지만, 나는 apnea.diving.deep에 동의합니다. – OscarRyz
코드 중복을 피하기 위해 이것을하고 싶습니다. 사실 추상 클래스는 추상적이지 않고, 모든 하위 클래스에 필요한 몇 가지 속성을 가지고 있으며 그 하위 클래스에 몇 가지 접근자가 있습니다. –
다른 코멘트에서, OP는 abstrac의 목적이 자녀가 필요로하는 행동 (방법)을 공유하는 것입니다. Ruby에서는 필요한 경우 메서드를 "혼합"하는 데 사용되는 모듈을 사용하는 것이 가장 좋습니다. 여기
module Foo
def foo
puts "foo!"
end
end
class Concrete
include Foo
end
Concrete.new.foo # => "foo!"
을하지만 원래 요청이 만족 될 수있는 방법은 다음과 같습니다 :
class Abstract
def foo
puts "foo!"
end
end
class Concrete
end
Concrete.new.foo # => "foo!"
이 : 대신 예를 들어
#!/usr/bin/ruby1.8
class Abstract
def initialize(*args)
raise if self.class == Abstract
super
end
end
class Concrete < Abstract
end
Concrete.new # OK
Abstract.new # Raises an exception
'Abstract
@ d135-1r43이면 레일즈에서 작동하지 않습니다. 레일즈 (2.2.8) 콘솔에서 작동하는 것 같습니다. 그것은 어떻게 파열됩니까? 나는 인수에 따라 Abstract의 ctor를 전달하는 것을 잊었습니다. 그게 수정 됐어. –
+1 믹스 인이가는 가장 좋은 방법입니다. – zetetic
당신이 STI를하고이를 원한다면, this thread에서 제안을 따를 수 있습니다 :
class Periodical < ActiveRecord::Base
private_class_method :new, :allocate
validates_presence_of :type
end
class Book < Periodical
public_class_method :new, :allocate
end
class Magazine < Periodical
public_class_method :new, :allocate
end
경고 : 이것이 효과적인 해결책인지 잘 모르겠습니다. 이렇게하면 new
과 allocate
이 기본 클래스에 숨겨져 하위 클래스에서 다시 활성화되지만 그만으로는 객체가 생성되는 것을 방지하지 못하는 것 같습니다. create!
. type
에 유효성 검사를 추가하면 기본 클래스가 작성되지 않습니다. 나는 create!
을 숨길 수 있다고 생각하지만 레일스가 모델 객체를 인스턴스화 할 수있는 모든 방법을 다룰 지 확신 할 수 없습니다.
일부 제 3자가 일부 스텁을 구현할 때 API를 적용하려면 거의 항상이 작업을 수행해야하며 사용자가 실수를 저지를 것이라고 확신 할 수 있습니다. 당신은 당신의 부모 클래스의 특정 접두사 템플릿을 사용할 수 있습니다과 창조에 내부적으로 점검 모듈이 달성 :
에게module Abstract
def check
local = self.methods - Object.methods
templates = []
methods = []
local.each do |l|
if l =~ /abstract_(.*)/ # <--- Notice we look for abstract_* methods to bind to.
templates.push $1
end
methods.push l.to_s
end
if !((templates & methods) == templates)
raise "Class #{self.class.name} does not implement the required interface #{templates}"
end
end
end
class AbstractParent
include Abstract
def initialize
check
end
def abstract_call # <--- One abstract method here
end
def normal_call
end
end
class Child < AbstractParent # <-- Bad child, no implementation
end
class GoodChild < AbstractParent
def call # <-- Good child, has an implementation
end
end
이 테스트 :
이begin
AbstractParent.new
puts "Created AbstractParent"
rescue Exception => e
puts "Unable to create AbstractParent"
puts e.message
end
puts
begin
Child.new
puts "Created Child"
rescue Exception => e
puts "Unable to create Child"
puts e.message
end
puts
begin
GoodChild.new
puts "Created GoodChild"
rescue Exception => e
puts "Unable to create GoodChild"
puts e.message
end
이 결과 :
이[~] ruby junk.rb
Unable to create AbstractParent
Class AbstractParent does not implement the required interface ["call"]
Unable to create Child
Class Child does not implement the required interface ["call"]
Created GoodChild
당신은 수 있습니다 Ruby에서이 작업을하지 않는 것이 훨씬 행복합니다. 루비는 이것도 필요로하지도 않으며 (당신이 알아내는 것처럼) 실제로 루비를 지원하지도 않습니다. –
씨를보고 싶습니다. @ Jörg W Mittag가 이에 대해 말해야합니다. – Zabba
@ Zabba : 한 마디 :하지 마라. :-) –