English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Ruby는 순수 object-oriented 언어로, Ruby의 모든 것은 객체 형태로 나타납니다. Ruby의 모든 값은 객체입니다. 심지어 가장 기본적인 것인 문자열, 숫자, 심지어 true와 false도 객체입니다. 클래스 자체도객체는 Class 클래스의 예제. 이 장에서는 Ruby object-oriented와 관련된 모든 주요 기능을 설명할 것입니다.
클래스는 객체의 형태를 지정하며, 데이터 표현과 메서드를 결합하여 데이터를 정리한 패키지입니다. 클래스의 데이터와 메서드는 클래스의 구성원으로 불립니다.
클래스를 정의할 때, 실제로는 데이터 타입의 블루프리ント을 정의하고 있습니다. 이는 실제 데이터를 정의하지 않으며, 클래스 이름이 의미하는 것을 정의하며, 즉, 클래스의 객체가 무엇으로 구성되고, 이 객체에서 수행할 수 있는 작업을 정의합니다.
으로 클래스 정의를 시작하며, class 으로 시작하고, 그 뒤에클래스 이름마지막으로 끝 로 구분하여 해당 클래스 정의를 종료합니다. 예를 들어, 우리는 다음과 같이 class 키워드를 사용하여 Box 클래스를 정의합니다:
class 박스 code 끝
习慣에 따라, 이름은 대문자로 시작해야하며, 여러 단어를 포함할 경우 각 단어의 첫 글자를 대문자로 만들어야 하며, 이 사이에는 구분자가 없습니다. 예를 들어: CamelCase.
클래스는 객체의 블루프리ント을 제공하므로, 대체로 객체는 클래스에 따라 생성됩니다. 우리는 new 키워드를 사용하여 클래스의 객체를 선언합니다. 다음과 같은 문장은 클래스 Box의 두 개의 객체를 선언합니다:
box1 = Box.new box2 = Box.new
initialize 메서드는 표준 Ruby 클래스 메서드로, 클래스의 생성자입니다. 다른 object-oriented programming 언어와의 생성자 작업 원리는 유사합니다. 객체를 생성하면서 일부 클래스 변수를 초기화하고 싶을 때 initialize 메서드가 유용합니다. 이 메서드는 여러 가지 매개변수를 가지며, Ruby의 다른 메서드와 마찬가지로 이 메서드를 사용할 때는 앞에 def 키워드를 사용하여 표현됩니다:
class 박스 def initialize(w,h) @width, @height = w, h 끝 끝
예제 변수객체 속성으로, 객체를 생성할 때마다 객체의 속성이 됩니다. 각 객체의 속성은 별도로 할당되며, 다른 객체와는 값을 공유하지 않습니다. 클래스 내부에서는 @ 연산자를 사용하여 이러한 속성에 접근하며, 클래스 외부에서는액세서 메서드의공개메서드를 사용하여 접근합니다. 아래는 정의된 클래스 Box 예제로, @width와 @height를 클래스 Box의 예제 변수로 사용합니다.
class 박스 def initialize(w,h) # 예제 변수에 값을 할당합니다 @width, @height = w, h 끝 끝
클래스 내에 정의된 변수를 외부에서 읽기 위해, 액세서(getter) 메서드를 정의하여 접근할 수 있습니다. 아래 예제는 액세서 메서드의 사용법을 보여줍니다:
#!/usr/빈/루비 -w # 클래스 정의 class 박스 # 생성자 def initialize(w,h) @width, @height = w, h 끝 # 访问器方法 def printWidth @width 끝 def printHeight @height 끝 끝 # 객체 생성, 박스의 높이와 너비 초기화 box = Box.new(10, 20) # 使用访问器方法 x = box.printWidth() y = box.printHeight() puts "박스 너비 : #{x}" puts "박스 높이 : #{y}"
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
박스 너비 : 10 박스 높이 : 20
변수 값에 접근하는 액세서 메서드와 유사하게, Ruby는 클래스 외부에서 클래스에 이미 정의된 변수에 매개변수를 전달하는 방법을 제공합니다. 이는 다른 이름으로세터 메서드정의는 다음과 같습니다:
#!/usr/빈/루비 -w # 클래스 정의 class 박스 # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # 访问器方法 def getWidth @width 끝 def getHeight @height 끝 # 设置器方法 def setWidth=(value) @width = value 끝 def setHeight=(value) @height = value 끝 끝 # 객체 생성 box = Box.new(10, 20) # 세터 메서드 사용 box.setWidth = 30 box.setHeight = 50 # 使用访问器方法 x = box.getWidth() y = box.getHeight() puts "박스 너비 : #{x}" puts "박스 높이 : #{y}"
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
박스 너비 : 30 박스 높이 : 50
두 가지 방법이 매우 일반적이기 때문에, Ruby는 attr_accessor :variable_name, attr_reader :variable_name, attr_writer :variable_name 세 가지 속성 선언 방법이 있습니다. 중에서:accessor=reader+writer입니다.
그리고 주의하세요: 변수 이름 앞에는 :이 있어야 하며, 변수 이름 사이에는 ,로 구분해야 합니다.
예제 메서드정의는 다른 메서드 정의와 같습니다. 모두 def 키워드지만, 그들은 단지 클래스 예제를 통해 사용될 수 있습니다. 예제와 같이. 그들의 기능은 예제 변수에 액세스하는 것에 국한되지 않으며, 사용자의 요구에 따라 더 많은 다른 작업을 수행할 수 있습니다.
#!/usr/빈/루비 -w # 클래스 정의 class 박스 # 생성자 def initialize(w,h) @width, @height = w, h 끝 # 예제 메서드 def getArea @width * @height 끝 끝 # 객체 생성 box = Box.new(10, 20) # 예제 메서드 호출 a = box.getArea() puts "박스의 면적은: #{a}"
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
박스의 면적은: 200
클래스 변수은 클래스의 모든 예제에서 공유되는 변수입니다. 다시 말해, 클래스 변수의 예제는 모든 객체 예제에 의해 접근될 수 있습니다. 클래스 변수는 두 개의 @ 문자(@@)로 전제자가 있으며, 클래스 변수는 클래스 정의 내에서 초기화되어야 합니다. 아래 예제와 같습니다.
클래스 메서드사용 def self.methodname() 정의는 클래스 메서드는 end 구분자로 끝납니다. 클래스 메서드는 클래스 이름을 가진 classname.methodname 형식 호출은 아래 예제와 같습니다:
#!/usr/빈/루비 -w class 박스 # 클래스 변수를 초기화합니다 @@count = 0 def initialize(w,h) # 예제 변수에 값을 할당합니다 @width, @height = w, h @@count += 1 끝 def self.printCount() puts "박스 개수는 : #@@count" 끝 끝 # 创建两个对象 box1 = Box.new(10, 20) box2 = Box.new(30, 100) # 调用类方法来输出盒子计数 Box.printCount()
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
Box count is: 2
You define any class has a to_s example method to return the string representation of the object. Below is a simple example that represents the Box object based on width and height:
#!/usr/빈/루비 -w class 박스 # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # to_s 메서드 정의 def to_s "(w:#@width,h:#@height)" # object string format 끝 끝 # 객체 생성 box = Box.new(10, 20) # to_s 메서드 자동 호출 puts "String representation of box is: #{box}"
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
String representation of box is: (w:10,h:20)
Ruby는 세 가지 수준의 예제 메서드 보호를 제공합니다.分别是 public, private 또는 protectedRuby는 예제 및 클래스 변수에 접근 제어를 적용하지 않습니다.
public 메서드: public 메서드는 어떤 객체든 호출할 수 있습니다. 기본적으로 모든 메서드는 public입니다. initialize 메서드는 항상 private입니다.
private 메서드: private 메서드는 클래스 외부에서 접근하거나 확인할 수 없습니다. 클래스 메서드만 접근할 수 있습니다.
protected 메서드: protected 메서드는 해당 클래스 및 서브 클래스 객체만이 호출할 수 있습니다. 접근도 클래스 및 서브 클래스 내에서만 가능합니다.
다음은 이 세 가지 접근자 수정자 문법을 보여주는 간단한 예제입니다:
#!/usr/빈/루비 -w # 클래스 정의 class 박스 # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # 예제 메서드는 기본적으로 public입니다 def getArea getWidth() * getHeight 끝 # private 접근자 메서드 정의 def getWidth @width 끝 def getHeight @height 끝 # private로 설정 private :getWidth, :getHeight # 면적 출력 예제 메서드 def printArea @area = getWidth() * getHeight puts "Big box area is: #@area" 끝 # 예제 메서드를 protected로 설정 protected :printArea 끝 # 객체 생성 box = Box.new(10, 20) # 예제 메서드 호출 a = box.getArea() puts "박스의 면적은: #{a}" # protected의 예제 메서드 호출 시도 box.printArea()
위의 코드가 실행될 때, 다음과 같은 결과를 생성합니다. 여기서, 첫 번째 메서드 호출이 성공했지만 두 번째 메서드는 문제를 일으킵니다.
박스의 면적은: 200 test.rb:42: protected method `printArea' called for # <Box:0xb7f11280 @height=20, @width=10> (NoMethodError)
상속을 지원합니다. 상속은面向对象编程에서 가장 중요한 개념 중 하나로, 다른 클래스를 기반으로 클래스를 정의할 수 있게 해줍니다. 이는 애플리케이션의 생성 및 유지보수를 더 쉽게 만듭니다.
상속은 코드 재사용과 빠른 실행을 돕습니다. 불운히 Ruby는 다중 상속을 지원하지 않지만, Ruby는 Mixin라고 합니다.
을 생성할 때, 프로그래머는 새로운 클래스가 특정 클래스의 멤버를 继承할 수 있도록 직접 지정할 수 있습니다. 이렇게 하면 새로운 데이터 멤버와 멤버 함수를 다시 작성하지 않아도 됩니다. 이 클래스는기본 클래스 또는 부모 클래스는추가 클래스 또는 서브 클래스입니다.
Ruby는 서브클래스화 개념도 제공합니다. 서브클래스화는 상속을 의미하며, 이를 통해 클래스를 확장할 수 있습니다. 서브클래스화의 문법은 매우 간단합니다. 클래스 문장에 < 문자와 부모 클래스 이름을 추가하면 됩니다. 예를 들어, 다음은 클래스 BigBox 는 Box 의 자식 클래스:
#!/usr/빈/루비 -w # 클래스 정의 class 박스 # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # 예제 메서드 def getArea @width * @height 끝 끝 # 서브 클래스 정의 class BigBox < Box # 새로운 예제 메서드 추가 def printArea @area = @width * @height puts "Big box area is: #@area" 끝 끝 # 객체 생성 box = BigBox.new(10, 20) # 면적 출력 box.printArea()
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
큰 박스 면적은 다음과 같습니다: 200
자식 클래스에서 새로운 기능을 추가할 수 있지만, 때로는 부모 클래스에서 정의된 메서드의 동작을 변경하고 싶을 수 있습니다. 이 경우 메서드 이름을 유지하면서 메서드 기능을 오버로드할 수 있습니다. 다음 예제를 참고하세요:
#!/usr/빈/루비 -w # 클래스 정의 class 박스 # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # 예제 메서드 def getArea @width * @height 끝 끝 # 서브 클래스 정의 class BigBox < Box # 기존 getArea 메서드 변경 def getArea @area = @width * @height puts "Big box area is: #@area" 끝 끝 # 객체 생성 box = BigBox.new(10, 20) # 오버로드된 메서드를 사용하여 면적 출력 box.getArea()
위 예제의 실행 결과는 다음과 같습니다:
큰 박스 면적은 다음과 같습니다: 200
사용하고 싶은 것은 + 연산자를 사용하여 두 Box 객체의 벡터 덧셈을 수행합니다 * 연산자를 사용하여 Box의 width와 height를 곱합니다 - Box의 width와 height를 반대로 계산하는 수학 연산자 정의된 Box 클래스 버전이 다음과 같습니다:
class 박스 def initialize(w,h) # width와 height 초기화 @width, @height = w, h 끝 def +(other) # 정의 + 벡터 덧셈을 수행합니다 Box.new(@width + other.width, @height + other.height) 끝 def -# 일원 연산자 정의 - width와 height를 반대로 계산합니다 Box.new(-@width, -@height) 끝 def *(scalar) # 执行标量乘法 Box.new(@width*scalar, @height*scalar) 끝 끝
有时候,我们想要防止对象被改变。在 Object 中,freeze 方法可实现这点,它能有效地把一个对象变成一个常量。任何对象都可以通过调用 Object.freeze 进行冻结。冻结对象不能被修改,也就是说,您不能改变它的示例变量。
您可以使用 Object.frozen? 方法检查一个给定的对象是否已经被冻结。如果对象已被冻结,该方法将返回 true,否则返回一个 false 值。下面的示例解释了这个概念:
#!/usr/빈/루비 -w # 클래스 정의 class 박스 # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # 访问器方法 def getWidth @width 끝 def getHeight @height 끝 # 设置器方法 def setWidth=(value) @width = value 끝 def setHeight=(value) @height = value 끝 끝 # 객체 생성 box = Box.new(10, 20) # 让我们冻结该对象 box.freeze if( box.frozen? ) puts "Box object is frozen object" else puts "Box object is normal object" 끝 # 现在尝试使用设置器方法 box.setWidth = 30 box.setHeight = 50 # 使用访问器方法 x = box.getWidth() y = box.getHeight() puts "Width of the box is : #{x}" puts "Height of the box is : #{y}"
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
Box object is frozen object test.rb:20:in `setWidth=': can't modify frozen object (TypeError) from test.rb:39
您可以在类的内部定义一个常量,通过把一个直接的数值或字符串值赋给一个变量来定义的,常量的定义不需要使用 @ 或 @@。按照惯例,常量的名称使用大写。
一旦常量被定义,您就不能改变它的值,您可以在类的内部直接访问常量,就像是访问变量一样,但是如果您想要在类的外部访问常量,那么您必须使用 classname::constant아래의 예제와 같이 표시됩니다.
#!/usr/빈/루비 -w # 클래스 정의 class 박스 BOX_COMPANY = "TATA Inc" BOXWEIGHT = 10 # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # 예제 메서드 def getArea @width * @height 끝 끝 # 객체 생성 box = Box.new(10, 20) # 예제 메서드 호출 a = box.getArea() puts "박스의 면적은: #{a}" puts Box::BOX_COMPANY puts "Box의 무게는: #{Box::BOXWEIGHT}"
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
박스의 면적은: 200 TATA Inc Box의 무게는: 10
클래스 상수는 상속될 수 있으며 예제 메서드와 마찬가지로 오버로드될 수 있습니다.
일정한 경우, 객체 생성자를 호출하지 않고 initialize 이 경우 객체를 생성하는 경우, 즉 new 메서드로 객체를 생성하는 경우, 이 경우 allocate를 호출하여 초기화되지 않은 객체를 생성할 수 있습니다. 아래의 예제를 보겠습니다:
#!/usr/빈/루비 -w # 클래스 정의 class 박스 attr_accessor :width, :height # 생성자 메서드 def initialize(w,h) @width, @height = w, h 끝 # 예제 메서드 def getArea @width * @height 끝 끝 # new로 객체 생성 box1 = Box.new(10, 20) # allocate로 다른 객체 생성 box2 = Box.allocate # box 사용1 예제 메서드 호출 a = box1.getArea() puts "박스의 면적은: #{a}" # box 사용2 예제 메서드 호출 a = box2.getArea() puts "박스의 면적은: #{a}"
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
박스의 면적은: 200 test.rb:14: warning: instance variable @width not initialized test.rb:14: warning: instance variable @height not initialized test.rb:14:in `getArea`: undefined method `* nil:NilClass (NoMethodError) from test.rb:29
Ruby의 self과 Java의 this는 비슷한 점이 있지만 매우 다릅니다. Java의 메서드는 예제 메서드에서 참조되기 때문에 this는 일반적으로 현재 객체를 가리킵니다. 반면 Ruby의 코드는 줄별로 실행되기 때문에 다른 상황(context)에서 self은 다른 의미를 가집니다. 아래의 예제를 보겠습니다.
#!/usr/빈/루비 -w class 박스 # 클래스 정보 출력 puts "self의 클래스 = #{self.class}" puts "self의 이름 = #{self.name}" 끝
위의 코드가 실행될 때, 다음과 같은 결과가 생성됩니다:
self의 클래스 = 클래스 self의 이름 = 박스
이는 클래스 정의가 현재 객체로서 실행될 때, 동시에 메타 클래스와 부모 클래스에서의 이 메서드가 메서드 정의 실행 중에 사용 가능하다는 것을 의미합니다.