답변:
첫 번째 대답은 좋으며 구조적 대답을 제공하지만 다른 접근 방식은 수행중인 작업에 대해 생각하는 것입니다. 모듈은 여러 클래스에서 사용할 수있는 메소드를 제공하는 것에 관한 것입니다. Rails 앱에서 볼 수 있듯이이를 "라이브러리"로 생각하십시오. 클래스는 객체에 관한 것입니다. 모듈은 기능에 관한 것입니다.
예를 들어 인증 및 권한 부여 시스템이 모듈의 좋은 예입니다. 인증 시스템은 여러 앱 수준 클래스에서 작동하며 (사용자는 인증되고, 세션은 인증을 관리하고, 다른 많은 클래스는 인증 상태에 따라 다르게 작동합니다.) 인증 시스템은 공유 API로 작동합니다.
여러 앱에서 메소드를 공유 할 때 모듈을 사용할 수도 있습니다 (다시 말해서 라이브러리 모델이 좋습니다).
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║ ║ class ║ module ║
╠═══════════════╬═══════════════════════════╬═════════════════════════════════╣
║ instantiation ║ can be instantiated ║ can *not* be instantiated ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ usage ║ object creation ║ mixin facility. provide ║
║ ║ ║ a namespace. ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ superclass ║ module ║ object ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ methods ║ class methods and ║ module methods and ║
║ ║ instance methods ║ instance methods ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inheritance ║ inherits behaviour and can║ No inheritance ║
║ ║ be base for inheritance ║ ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inclusion ║ cannot be included ║ can be included in classes and ║
║ ║ ║ modules by using the include ║
║ ║ ║ command (includes all ║
║ ║ ║ instance methods as instance ║
║ ║ ║ methods in a class/module) ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ extension ║ can not extend with ║ module can extend instance by ║
║ ║ extend command ║ using extend command (extends ║
║ ║ (only with inheritance) ║ given instance with singleton ║
║ ║ ║ methods from module) ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
아직 아무도이 말을하지 않은 것에 놀랐습니다.
asker는 Java 배경에서 나왔으므로 (그리고 나도 마찬가지), 여기에 도움이되는 비유가 있습니다.
클래스는 단순히 Java 클래스와 같습니다.
모듈은 Java 정적 클래스와 같습니다. Math
자바 클래스를 생각하십시오 . 인스턴스화하지 않고 정적 클래스 (예 :)의 메소드를 재사용합니다 Math.random()
.
extend self
)하여 메소드를 self
메타 클래스에서 사용할 수있게합니다 . 이로써 같은 방법을 파견 할 수 random()
A의 Math
모듈. 그러나 본질적으로 모듈의 메소드는 모듈 자체에서 호출 할 수 없습니다 self
. 이는 Ruby의 개념 self
, 메타 클래스 및 메소드 조회 작동 방식과 관련이 있습니다. 자세한 내용은 "Metaprogramming Ruby"-Paolo Perlotta를 확인하십시오.
기본적으로 모듈을 인스턴스화 할 수 없습니다. 클래스에 모듈이 포함되면 모든 모듈 메소드와 클래스 메소드에 대한 액세스를 제공하는 프록시 수퍼 클래스가 생성됩니다.
모듈은 여러 클래스로 포함될 수 있습니다. 모듈은 상속 될 수 없지만이 "mixin"모델은 유용한 유형의 "다중 상속"을 제공합니다. OO 순수 주의자들은 그 진술에 동의하지 않지만, 순결이 일을 끝내는 것을 방해하지는 않을 것이다.
(이 답변은 원래에 연결 http://www.rubycentral.com/pickaxe/classes.html
되었지만 해당 링크 및 해당 도메인은 더 이상 활성화되어 있지 않습니다.)
extend
는 클래스를 호출하여 "정적"과 같은 메소드를 취할 수 있습니다 . 루비는 실제로 "인스턴스"와 "클래스 / 정적"메소드를 전혀 구분하지 않으며 그 메소드의 수신자 만 구분합니다.
네임 스페이스 : 모듈은 네임 스페이스입니다 ... Java에는 존재하지 않습니다.)
또한 Java와 Python에서 Ruby로 전환했는데 정확히 같은 질문이 있었음을 기억합니다 ...
따라서 가장 간단한 대답은 모듈이 네임 스페이스이며 Java에는 존재하지 않는다는 것입니다. 자바에서 네임 스페이스에 가장 가까운 사고 방식은 패키지 입니다.
그래서 루비의 모듈은 java의
클래스 와 같습니다 : class? 어떤
인터페이스를하지? 어떤
추상 클래스하지? 어떤
패키지 없다? 예 (아마도)
자바 클래스 내부의 정적 메소드 : 루비의 모듈 내부 메소드와 동일
자바에서 최소 단위는 클래스이므로 클래스 외부에서는 함수를 가질 수 없습니다. 그러나 루비에서는 (파이썬과 같이) 가능합니다.
그렇다면 모듈은 무엇입니까?
클래스, 메소드, 상수. 모듈은 해당 네임 스페이스 아래에서이를 보호합니다.
인스턴스 없음 : 모듈을 사용하여 인스턴스를 만들 수 없음
혼합 기능 : 때로는 상속 모델이 클래스에는 좋지 않지만 기능면에서 클래스 / 메소드 / 상수 세트를 그룹화하려고합니다.
루비의 모듈에 대한 규칙 :
-모듈 이름은 UpperCamelCase입니다
-모듈 내의 상수는 모두 CAPS입니다 (이 규칙은 모듈에 한정되지 않은 모든 루비 상수에 대해 동일합니다)
-액세스 방법 : use. 연산자
-상수 액세스 : use :: symbol
모듈의 간단한 예 :
module MySampleModule
CONST1 = "some constant"
def self.method_one(arg1)
arg1 + 2
end
end
모듈 내에서 메소드를 사용하는 방법 :
puts MySampleModule.method_one(1) # prints: 3
모듈 상수를 사용하는 방법 :
puts MySampleModule::CONST1 # prints: some constant
모듈에 대한 몇 가지 다른 규칙 :
파일에서 하나의 모듈 사용 (예 : 루비 클래스, 루비 파일 당 하나의 클래스)
수업
클래스를 정의 할 때 데이터 유형에 대한 청사진을 정의합니다. 클래스 보유 데이터, 해당 데이터와 상호 작용하고 객체를 인스턴스화하는 데 사용되는 메소드가 있습니다.
구성 단위
모듈은 메소드, 클래스 및 상수를 그룹화하는 방법입니다.
모듈은 두 가지 주요 이점을 제공합니다.
=> 모듈은 네임 스페이스를 제공하고 이름 충돌을 방지합니다. 네임 스페이스는 다른 사람이 작성한 것과 동일한 이름을 가진 함수 및 클래스와의 충돌을 피하는 데 도움이됩니다.
=> 모듈은 mixin 기능을 구현합니다.
(Klazz에 모듈을 포함하면 Klazz 인스턴스가 모듈 메소드에 액세스 할 수 있습니다.)
(클래 즈 클래스에 Mods 메소드에 대한 액세스 권한을 부여하는 Mod로 Klazz를 확장하십시오.)
첫째, 아직 언급되지 않은 몇 가지 유사점. 루비는 공개 클래스를 지원하지만 개방형 모듈도 지원합니다. 결국 클래스는 클래스 상속 체인의 모듈에서 상속되므로 클래스와 모듈에는 비슷한 동작이 있습니다.
그러나 프로그래밍 언어로 클래스와 모듈을 함께 사용하는 목적이 무엇인지 스스로에게 물어볼 필요가 있습니까? 클래스는 인스턴스를 만들기위한 청사진으로 만들어졌으며 각 인스턴스는 청사진의 실현 된 변형입니다. 인스턴스는 청사진 (클래스)의 실현 된 변형입니다. 당연히 클래스는 객체 생성 기능을합니다. 또한 한 청사진이 다른 청사진에서 파생되기를 원하기 때문에 클래스는 상속을 지원하도록 설계되었습니다.
모듈을 인스턴스화 할 수 없으며 객체를 만들지 않으며 상속을 지원하지 않습니다. 따라서 한 모듈은 다른 모듈을 상속하지 않습니다.
그렇다면 언어로 모듈을 갖는 요점은 무엇입니까? 모듈을 분명히 사용하는 방법 중 하나는 네임 스페이스를 만드는 것이므로 다른 언어에서도이를 알 수 있습니다. 다시, 루비에 대한 멋진 점은 모듈을 다시 열 수 있다는 것입니다 (클래스처럼). 그리고 이것은 다른 Ruby 파일에서 네임 스페이스를 재사용하려고 할 때 큰 사용법입니다.
module Apple
def a
puts 'a'
end
end
module Apple
def b
puts 'b'
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c527c98>
> f.a
=> a
> f.b
=> b
그러나 모듈 간에는 상속이 없습니다.
module Apple
module Green
def green
puts 'green'
end
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c462420>
> f.green
NoMethodError: undefined method `green' for #<Fruit:0x007fe90c462420>
Apple 모듈은 Green 모듈에서 메소드를 상속하지 않았으며 Fruit 클래스에 Apple을 포함 시키면 Apple 모듈의 메소드가 Apple 인스턴스의 상위 체인에 추가되지만 Green 모듈의 메소드는 추가되지 않습니다. 모듈은 Apple 모듈에서 정의되었습니다.
그렇다면 친환경 방법에 어떻게 접근 할 수 있습니까? 클래스에 명시 적으로 포함시켜야합니다.
class Fruit
include Apple::Green
end
=> Fruit
> f.green
=> green
그러나 Ruby에는 모듈에 대한 또 다른 중요한 사용법이 있습니다. 이것은 Mixin 시설이며, SO에 대한 다른 답변으로 설명합니다. 그러나 요약하면 믹스 인을 사용하여 객체의 상속 체인에 메소드를 정의 할 수 있습니다. 믹스 인을 통해 객체 인스턴스의 상속 체인 (include) 또는 singleton_class of self (extend)에 메소드를 추가 할 수 있습니다.