Elixir의 OOP 소개
13451 단어 elixirphoenixrubycomputerscience
이것은 누구를 위한 것입니까?
다른 많은 사람들과 마찬가지로 저는 Phoenix 프레임워크를 통해 Elixir 언어를 알게 되었고 Phoenix 외부에서 Elixir를 작성하는 데 관심을 갖게 되었습니다. 그러나 불변성과 클래스 메서드의 부족으로 인해 가장 큰 도전은 무엇이든 수행하는 방법을 알아내는 것이었습니다.
이 게시물은 OOP 프로그래밍 지식을 생산적인 Elixir 코드로 전환하는 방법에 대해 배운 몇 가지 중요한 교훈을 살펴보기 위한 것입니다. 이러한 요점의 대부분은 매우 간단하며 생각에서 "클릭"만 하면 됩니다.
기능과 데이터는 별개
대부분의 OOP 언어에서는 프로그램 작업을 수행하기 위해 클래스(객체)의 인스턴스를 사용합니다. 각 인스턴스에는 자체 포함된 상태와 해당 상태를 참조하여 작업을 수행할 수 있는 함수가 있습니다. 예를 들어 간단한 Ruby 클래스는 다음과 같습니다.
class Person
def initialize(name)
@cust_name = name
end
def name_backwards
@cust_name.reverse
end
end
person_1 = Person.new('Ted')
person_1.name_backwards
# outputs "deT"
Elixir 함수는 this
, @
또는 다른 인스턴스 변수에 대한 참조를 가질 수 없습니다. 따라서 Elixir에서 유사한 작업을 수행하는 방법은 함수가 데이터(인스턴스)를 첫 번째 매개변수로 사용하도록 하는 것입니다. 다음은 Elixir로 재작성한 위의 Ruby 코드입니다.
person = %{name: "Ted"}
defmodule Person.Functions do
def name_backwards(person) do
String.reverse(person.name)
end
end
Person.Functions.name_backwards(person)
위의 코드에서 개인 인스턴스의 데이터가 Person.Functions 모듈 외부에 완전히 보관되어 있음을 알 수 있습니다. person 인스턴스에서 함수를 사용하려면 person 인스턴스를 첫 번째 매개 변수로 사용하는 함수에 전달합니다.
실제로 모듈은 이름이 지정되지 않습니다Person.Functions
. 모듈은 정의에 따라 개인 인스턴스에 연결되어 있지 않기 때문입니다. name_backwards
함수는 이름 필드가 있는 모든 개체에 사용할 수 있습니다.
교체로 업데이트
OOP에서 가장 일반적인 작업 중 하나는 개체의 인스턴스를 사용하여 일부 상태를 추적하는 것입니다. 예를 들어 루비에서
class Person
def initialize(age)
@person_age = age
end
def add_year
@person_age = @person_age + 1
end
def get_age
@person_age
end
end
person_1 = Person.new(30)
person_1.add_year
person_1.add_year
person_1.get_age
# outputs 32
Elixir에서 모든 객체는 변경할 수 없습니다. 그렇다면 도대체 어떻게 이 사람 인스턴스의 필드를 업데이트할 수 있을까요? 새 사람 인스턴스를 만들고 이전 인스턴스를 교체하여 수행할 수 있습니다.
person = %{age: 30}
defmodule Person.Functions do
def add_year(person) do
new_age = person.age + 1
%{age: new_age}
end
def get_age(person) do
person.age
end
end
person = Person.Functions.add_year(person)
person = Person.Functions.add_year(person)
Person.Functions.get_age(person)
따라서 인스턴스 내의 필드 값을 변경하는 대신 %{age: new_age}
줄에 새 인스턴스를 반환합니다.
전역 개체는 프로세스에 저장됩니다.
전역 상태의 사용을 옹호하는 것은 아니지만 이 아이디어가 Elixir의 기초를 배우는 데 근본적으로 중요하다고 생각합니다. 또한 이것은 인위적인 예일 수 있지만 OOP를 Elixir로 번역하는 도전을 보여줄 것이라고 생각합니다.
티켓을 분배하는 티켓 클래스를 추가했습니다. 각 사람이 고유한 티켓을 얻을 수 있도록 각 티켓이 나가는 대로 추적합니다. 정적 필드@@ticket_count
를 사용하여 티켓을 추적할 수 있으므로 Ruby에서는 매우 간단합니다.
class Tickets
@@ticket_count = 1
def self.get_ticket
next_ticket = @@ticket_count
@@ticket_count = @@ticket_count + 1
next_ticket
end
end
class Person
def initialize()
@ticket_num = -1
end
def get_ticket
@ticket_num = Tickets.get_ticket
@ticket_num
end
end
person_1 = Person.new()
puts person_1.get_ticket
#outputs 1
person_2 = Person.new()
puts person_2.get_ticket
#outputs 2
그러면 Elixir에서 티켓 수를 어떻게 추적할 수 있을까요? GenServer라는 것을 사용합니다.
defmodule Tickets do
use GenServer
def start_link(start_ticket_num) do
GenServer.start_link(Tickets, start_ticket_num, name: Tickets)
end
def get_ticket() do
GenServer.call Tickets, :get_ticket
end
def handle_call(:get_ticket, _from, curr_ticket_num) do
{:reply, curr_ticket_num, curr_ticket_num + 1}
end
end
defmodule Person.Functions do
def get_ticket(person) do
next_ticket = Tickets.get_ticket()
%{ticket_num: next_ticket}
end
end
Tickets.start_link(1)
person_1 = %{ticket_num: -1}
IO.inspect Person.Functions.get_ticket(person_1)
#output %{ticket_num: 1}
person_2 = %{ticket_num: -1}
IO.inspect Person.Functions.get_ticket(person_2)
# %{ticket_num: 2}
이제 이것은 점점 더 발전하고 있지만 Elixir의 진정한 아름다움입니다. start_link(1)
함수에서 초기 값이 1인 Tickets라는 이름의 GenServer 인스턴스로 다른 프로세스를 시작했습니다.
GenServer는 많은 일을 할 수 있지만 여기서는 현재 티켓 번호를 저장하는 데 사용합니다. get_ticket
를 호출할 때마다 코드는 기본적으로 {:reply, curr_ticket_num, curr_ticket_num + 1}
형식의 GenServer에 대한 주문인 응답{command_to_genserver, response_value, new_state_value}
으로 흐릅니다. 이제 모든 Elixir 모듈은 Tickets.get_ticket
함수를 호출하기만 하면 티켓을 얻을 수 있습니다.
대부분의 OOP 언어에서 다른 프로세스를 시작하는 것은 매우 높은 수준의 작업입니다. 실제로 개발자는 몇 년 동안 기본 프로세스에서만 작업할 수 있습니다. 그러나 Elixir에서는 다른 프로세스와 함께 작업하는 것이 기본 기술입니다.
GenServers에 대해 자세히 알고 싶다면 직접 작성하는 것이 좋습니다! 여기는 tutorial
마무리
이것이 Elixir 학습의 어려움에 대해 돌이켜 생각했을 때 처음으로 떠오른 몇 가지 사항이었습니다. 그들 중 하나가 당신에게 도움이 되었기를 바랍니다.
Elixir의 코딩은 재미있습니다!
Reference
이 문제에 관하여(Elixir의 OOP 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/bakenator/intro-to-oop-in-elixir-3c9i
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
대부분의 OOP 언어에서는 프로그램 작업을 수행하기 위해 클래스(객체)의 인스턴스를 사용합니다. 각 인스턴스에는 자체 포함된 상태와 해당 상태를 참조하여 작업을 수행할 수 있는 함수가 있습니다. 예를 들어 간단한 Ruby 클래스는 다음과 같습니다.
class Person
def initialize(name)
@cust_name = name
end
def name_backwards
@cust_name.reverse
end
end
person_1 = Person.new('Ted')
person_1.name_backwards
# outputs "deT"
Elixir 함수는
this
, @
또는 다른 인스턴스 변수에 대한 참조를 가질 수 없습니다. 따라서 Elixir에서 유사한 작업을 수행하는 방법은 함수가 데이터(인스턴스)를 첫 번째 매개변수로 사용하도록 하는 것입니다. 다음은 Elixir로 재작성한 위의 Ruby 코드입니다.person = %{name: "Ted"}
defmodule Person.Functions do
def name_backwards(person) do
String.reverse(person.name)
end
end
Person.Functions.name_backwards(person)
위의 코드에서 개인 인스턴스의 데이터가 Person.Functions 모듈 외부에 완전히 보관되어 있음을 알 수 있습니다. person 인스턴스에서 함수를 사용하려면 person 인스턴스를 첫 번째 매개 변수로 사용하는 함수에 전달합니다.
실제로 모듈은 이름이 지정되지 않습니다
Person.Functions
. 모듈은 정의에 따라 개인 인스턴스에 연결되어 있지 않기 때문입니다. name_backwards
함수는 이름 필드가 있는 모든 개체에 사용할 수 있습니다.교체로 업데이트
OOP에서 가장 일반적인 작업 중 하나는 개체의 인스턴스를 사용하여 일부 상태를 추적하는 것입니다. 예를 들어 루비에서
class Person
def initialize(age)
@person_age = age
end
def add_year
@person_age = @person_age + 1
end
def get_age
@person_age
end
end
person_1 = Person.new(30)
person_1.add_year
person_1.add_year
person_1.get_age
# outputs 32
Elixir에서 모든 객체는 변경할 수 없습니다. 그렇다면 도대체 어떻게 이 사람 인스턴스의 필드를 업데이트할 수 있을까요? 새 사람 인스턴스를 만들고 이전 인스턴스를 교체하여 수행할 수 있습니다.
person = %{age: 30}
defmodule Person.Functions do
def add_year(person) do
new_age = person.age + 1
%{age: new_age}
end
def get_age(person) do
person.age
end
end
person = Person.Functions.add_year(person)
person = Person.Functions.add_year(person)
Person.Functions.get_age(person)
따라서 인스턴스 내의 필드 값을 변경하는 대신 %{age: new_age}
줄에 새 인스턴스를 반환합니다.
전역 개체는 프로세스에 저장됩니다.
전역 상태의 사용을 옹호하는 것은 아니지만 이 아이디어가 Elixir의 기초를 배우는 데 근본적으로 중요하다고 생각합니다. 또한 이것은 인위적인 예일 수 있지만 OOP를 Elixir로 번역하는 도전을 보여줄 것이라고 생각합니다.
티켓을 분배하는 티켓 클래스를 추가했습니다. 각 사람이 고유한 티켓을 얻을 수 있도록 각 티켓이 나가는 대로 추적합니다. 정적 필드@@ticket_count
를 사용하여 티켓을 추적할 수 있으므로 Ruby에서는 매우 간단합니다.
class Tickets
@@ticket_count = 1
def self.get_ticket
next_ticket = @@ticket_count
@@ticket_count = @@ticket_count + 1
next_ticket
end
end
class Person
def initialize()
@ticket_num = -1
end
def get_ticket
@ticket_num = Tickets.get_ticket
@ticket_num
end
end
person_1 = Person.new()
puts person_1.get_ticket
#outputs 1
person_2 = Person.new()
puts person_2.get_ticket
#outputs 2
그러면 Elixir에서 티켓 수를 어떻게 추적할 수 있을까요? GenServer라는 것을 사용합니다.
defmodule Tickets do
use GenServer
def start_link(start_ticket_num) do
GenServer.start_link(Tickets, start_ticket_num, name: Tickets)
end
def get_ticket() do
GenServer.call Tickets, :get_ticket
end
def handle_call(:get_ticket, _from, curr_ticket_num) do
{:reply, curr_ticket_num, curr_ticket_num + 1}
end
end
defmodule Person.Functions do
def get_ticket(person) do
next_ticket = Tickets.get_ticket()
%{ticket_num: next_ticket}
end
end
Tickets.start_link(1)
person_1 = %{ticket_num: -1}
IO.inspect Person.Functions.get_ticket(person_1)
#output %{ticket_num: 1}
person_2 = %{ticket_num: -1}
IO.inspect Person.Functions.get_ticket(person_2)
# %{ticket_num: 2}
이제 이것은 점점 더 발전하고 있지만 Elixir의 진정한 아름다움입니다. start_link(1)
함수에서 초기 값이 1인 Tickets라는 이름의 GenServer 인스턴스로 다른 프로세스를 시작했습니다.
GenServer는 많은 일을 할 수 있지만 여기서는 현재 티켓 번호를 저장하는 데 사용합니다. get_ticket
를 호출할 때마다 코드는 기본적으로 {:reply, curr_ticket_num, curr_ticket_num + 1}
형식의 GenServer에 대한 주문인 응답{command_to_genserver, response_value, new_state_value}
으로 흐릅니다. 이제 모든 Elixir 모듈은 Tickets.get_ticket
함수를 호출하기만 하면 티켓을 얻을 수 있습니다.
대부분의 OOP 언어에서 다른 프로세스를 시작하는 것은 매우 높은 수준의 작업입니다. 실제로 개발자는 몇 년 동안 기본 프로세스에서만 작업할 수 있습니다. 그러나 Elixir에서는 다른 프로세스와 함께 작업하는 것이 기본 기술입니다.
GenServers에 대해 자세히 알고 싶다면 직접 작성하는 것이 좋습니다! 여기는 tutorial
마무리
이것이 Elixir 학습의 어려움에 대해 돌이켜 생각했을 때 처음으로 떠오른 몇 가지 사항이었습니다. 그들 중 하나가 당신에게 도움이 되었기를 바랍니다.
Elixir의 코딩은 재미있습니다!
Reference
이 문제에 관하여(Elixir의 OOP 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/bakenator/intro-to-oop-in-elixir-3c9i
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Person
def initialize(age)
@person_age = age
end
def add_year
@person_age = @person_age + 1
end
def get_age
@person_age
end
end
person_1 = Person.new(30)
person_1.add_year
person_1.add_year
person_1.get_age
# outputs 32
person = %{age: 30}
defmodule Person.Functions do
def add_year(person) do
new_age = person.age + 1
%{age: new_age}
end
def get_age(person) do
person.age
end
end
person = Person.Functions.add_year(person)
person = Person.Functions.add_year(person)
Person.Functions.get_age(person)
전역 상태의 사용을 옹호하는 것은 아니지만 이 아이디어가 Elixir의 기초를 배우는 데 근본적으로 중요하다고 생각합니다. 또한 이것은 인위적인 예일 수 있지만 OOP를 Elixir로 번역하는 도전을 보여줄 것이라고 생각합니다.
티켓을 분배하는 티켓 클래스를 추가했습니다. 각 사람이 고유한 티켓을 얻을 수 있도록 각 티켓이 나가는 대로 추적합니다. 정적 필드
@@ticket_count
를 사용하여 티켓을 추적할 수 있으므로 Ruby에서는 매우 간단합니다.class Tickets
@@ticket_count = 1
def self.get_ticket
next_ticket = @@ticket_count
@@ticket_count = @@ticket_count + 1
next_ticket
end
end
class Person
def initialize()
@ticket_num = -1
end
def get_ticket
@ticket_num = Tickets.get_ticket
@ticket_num
end
end
person_1 = Person.new()
puts person_1.get_ticket
#outputs 1
person_2 = Person.new()
puts person_2.get_ticket
#outputs 2
그러면 Elixir에서 티켓 수를 어떻게 추적할 수 있을까요? GenServer라는 것을 사용합니다.
defmodule Tickets do
use GenServer
def start_link(start_ticket_num) do
GenServer.start_link(Tickets, start_ticket_num, name: Tickets)
end
def get_ticket() do
GenServer.call Tickets, :get_ticket
end
def handle_call(:get_ticket, _from, curr_ticket_num) do
{:reply, curr_ticket_num, curr_ticket_num + 1}
end
end
defmodule Person.Functions do
def get_ticket(person) do
next_ticket = Tickets.get_ticket()
%{ticket_num: next_ticket}
end
end
Tickets.start_link(1)
person_1 = %{ticket_num: -1}
IO.inspect Person.Functions.get_ticket(person_1)
#output %{ticket_num: 1}
person_2 = %{ticket_num: -1}
IO.inspect Person.Functions.get_ticket(person_2)
# %{ticket_num: 2}
이제 이것은 점점 더 발전하고 있지만 Elixir의 진정한 아름다움입니다.
start_link(1)
함수에서 초기 값이 1인 Tickets라는 이름의 GenServer 인스턴스로 다른 프로세스를 시작했습니다.GenServer는 많은 일을 할 수 있지만 여기서는 현재 티켓 번호를 저장하는 데 사용합니다.
get_ticket
를 호출할 때마다 코드는 기본적으로 {:reply, curr_ticket_num, curr_ticket_num + 1}
형식의 GenServer에 대한 주문인 응답{command_to_genserver, response_value, new_state_value}
으로 흐릅니다. 이제 모든 Elixir 모듈은 Tickets.get_ticket
함수를 호출하기만 하면 티켓을 얻을 수 있습니다.대부분의 OOP 언어에서 다른 프로세스를 시작하는 것은 매우 높은 수준의 작업입니다. 실제로 개발자는 몇 년 동안 기본 프로세스에서만 작업할 수 있습니다. 그러나 Elixir에서는 다른 프로세스와 함께 작업하는 것이 기본 기술입니다.
GenServers에 대해 자세히 알고 싶다면 직접 작성하는 것이 좋습니다! 여기는 tutorial
마무리
이것이 Elixir 학습의 어려움에 대해 돌이켜 생각했을 때 처음으로 떠오른 몇 가지 사항이었습니다. 그들 중 하나가 당신에게 도움이 되었기를 바랍니다.
Elixir의 코딩은 재미있습니다!
Reference
이 문제에 관하여(Elixir의 OOP 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/bakenator/intro-to-oop-in-elixir-3c9i
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Elixir의 OOP 소개), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/bakenator/intro-to-oop-in-elixir-3c9i텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)