반응형

줄리아 Julia의 추상(Abstract) 타입, 구체(Concrete) 타입 , Mutable 타입, multiple dispatch, 타입 생성자(Type constructor)에 대해 다룹니다. 

 

2024. 01. 20  최초 작성




다음 사이트를 참고하고 ChatGPT의 도움을 받았습니다. 

https://techytok.com/lesson-types/



Julia 개발 환경 구축은 다음 포스트를 참고하세요. 

 

Visual Studio Code 사용한 Julia 개발 환경만들기(Windows / Ubuntu / Macbook M1)

https://webnautes.tistory.com/2216 



Julia 강좌를 진행하고 있습니다.

 

Julia 강좌 1 - 변수와 데이터 타입

https://webnautes.tistory.com/2218 

 

Julia 강좌 2 - 함수, void function,  Optional positional arguments, Keyword arguments

https://webnautes.tistory.com/2220 

 

Julia 강좌 3 - 배열, 튜플, 딕셔너리

https://webnautes.tistory.com/2229 

 

Julia 강좌 4 - 제어문 if ... else, for, break, continue, while, enumerate

https://webnautes.tistory.com/2235 

 

Julia 강좌 5 - 브로드캐스팅(broadcasting)

https://webnautes.tistory.com/2240 

 

Julia 강좌 6 - 변수 유효 범위( Variable Scope ) : 전역(global), 로컬(local)

https://webnautes.tistory.com/2247

 

Julia 강좌 7 - 모듈(module)

https://webnautes.tistory.com/2253 

 

Julia 강좌 8 - 타입(type)

https://webnautes.tistory.com/2260


Julia 강좌 9 - 패키지(package)

https://webnautes.tistory.com/2268 




줄리아(Julia) 언어에는 추상(abstract) 타입과 구체(concrete) 타입이 있습니다.



1. 추상(Abstract) 타입

   추상 타입은 다른 타입들의 상위 타입으로 사용되며  직접적으로 인스턴스를 생성할 수 없습니다. 즉, 이 타입의 변수를 생성할 수 없습니다.  이들은 타입 계층 구조에서 다른 타입들을 분류하고 조직하는 데 사용됩니다.

   추상 타입은 다형성을 지원하는 데 주로 사용됩니다. 예를 들어, 여러 구체 타입들이 공통의 추상 타입을 상속받아, 함수에서 이 추상 타입을 사용함으로써 다양한 구체 타입들에 대해 작동할 수 있습니다.

   예로 들어 Number는 모든 숫자 타입의 추상 타입이고 Integer와 FloatingPoint는 Number의 하위 타입입니다.

 

2. 구체(Concrete) 타입:

   구체 타입은 데이터의 실제 구조를 정의하며, 인스턴스화가 가능합니다. 즉, 이 타입의 변수를 생성하고, 값을 할당할 수 있습니다.

   구체 타입은 프로그램에서 실제 데이터를 담는 데 사용됩니다. 각 구체 타입은 특정한 데이터 구조와 연산을 가지고 있습니다.

   예로들어 Int32 타입의 변수를 생성하여 32비트 정수를 저장할 수 있으며 Float64 타입의 변수를 생성하여 64비트 부동 소수점 숫자를 저장할 수 있습니다. 



타입을 선언할 때는 type 또는 struct 키워드를 사용합니다.

 

# 추상 타입 Animal을 정의합니다.
# 추상 타입은 인스턴스를 생성할 수 없으며, 다른 타입들의 상위 타입으로 사용됩니다.
abstract type Animal end

# 추상 타입 Animal을 상속받는 구체 타입 Dog와 Cat을 정의합니다.
struct Dog <: Animal
    name::String
    age::Int
end

struct Cat <: Animal
    name::String
    age::Int
end

# 추상 타입을 인수로 받는 함수
function introduce(animal::Animal)
    println("This is a $(typeof(animal)) named $(animal.name).")
end

# 구체 타입의 인스턴스를 생성합니다.
# 구체 타입은 실제 데이터 구조를 가지며 인스턴스를 생성할 수 있습니다.
buddy = Dog("Buddy", 5)          # Dog 구체 타입의 인스턴스입니다.
whiskers = Cat("Whiskers", 3# Cat 구체 타입의 인스턴스입니다.


# introduce 함수는 구체 타입 인스턴스를 인자로 받아서 정보를 출력합니다.
introduce(buddy)   
# This is a Dog named Buddy.

introduce(whiskers)
# This is a Cat named Whiskers.




# 추상 타입으로 Person 타입을 정의한 후, 하위 타입도 추상 타입으로  Musician 타입을 정의합니다.
abstract type Person
end

abstract type Musician <: Person
end


# Musician의 하위 타입으로 구체 타입  Rockstart 타입과 ClassiMusician타입을 선언합니다.
# Rockstart 타입은 요소의 값을 변경할 수 있도록 mutable로 정의되었지만
# ClassicMusician은 요소의 값을 변경할 수 없도록 정의 되었습니다.
mutable struct Rockstar <: Musician
name::String
instrument::String
bandName::String
headbandColor::String
instrumentsPlayed::Int
end

struct ClassicMusician <: Musician
name::String
instrument::String
end


# ClassicMusician 타입은 값을 변경할 수 없습니다.
musician = ClassicMusician("Aurelio", "Violin")
println(musician)
# ClassicMusician("Aurelio", "Violin")

# Rockstart 타입은 값을 변경할 수 있습니다.
ricky = Rockstar("Riccardo", "Voice", "Black Lotus", "red", 2)
ricky.headbandColor="yellow"
println(ricky)
# Rockstar("Riccardo", "Voice", "Black Lotus", "yellow", 2)




multiple dispatch

추상 타입으로 인자를 정의하는 함수를 작성할 수 있습니다. 

다음 예제코드에서  introduceMe 함수는 Pserson 추상 타입으로 인자를 정의해서   Pserson 추상 타입의 하위 타입인  Rockstar 구체 타입과 Rockstar 구체 타입에서 사용가능합니다.

 

abstract type Person
end

abstract type Musician <: Person
end

mutable struct Rockstar <: Musician
name::String
instrument::String
bandName::String
headbandColor::String
instrumentsPlayed::Int
end

struct ClassicMusician <: Musician
name::String
instrument::String
end

ricky = Rockstar("Riccardo", "Voice", "Black Lotus", "red", 2)

aure = ClassicMusician("Aurelio", "Violin")

function introduceMe(person::Person)
    println("Hello, my name is $(person.name).")
end

introduceMe(aure)
# Hello, my name is Aurelio.

introduceMe(ricky)
# Hello, my name is Riccardo.



introduceMe 함수가 특정 구체 타입에서만 동작하도록 할 수도 있습니다. 

 

abstract type Person
end

abstract type Musician <: Person
end

mutable struct Rockstar <: Musician
name::String
instrument::String
bandName::String
headbandColor::String
instrumentsPlayed::Int
end

struct ClassicMusician <: Musician
name::String
instrument::String
end

ricky = Rockstar("Riccardo", "Voice", "Black Lotus", "red", 2)

aure = ClassicMusician("Aurelio", "Violin")

function introduceMe(person::Musician)
    println("Hello, my name is $(person.name) and I play $(person.instrument).")
end

introduceMe(aure)
# Hello, my name is Aurelio and I play Violin.



타입 생성자(Type constructor)

타입이 생성될 때  생성자 함수를 사용하여 기본값을 할당하거나 초기 계산을 하도록 할 수 있습니다.

다음 예제 코드에서는 타입 생성시 초기 계산을 수행하도록 합니다. 

 

mutable struct MyData
x::Float64
x2::Float64
y::Float64
z::Float64

    function MyData(x::Float64, y::Float64)

        # 함수의 인자로 전달받은 x,y를 사용하여 x2와 z를 계산합니다.
x2=x^2
z = sin(x2+y)

        # MyData 객체를 생성하여 리턴합니다.
    new(x, x2, y, z)
end
end

print(MyData(2.0, 3.0))




타입을 생성할때 타입 정보를 받도록 할 수 있습니다.

 

mutable struct MyData2{T<:Real}
x::T
x2::T
y::T
z::Float64

function MyData2{T}(x::T, y::T) where {T<:Real}
x2=x^2
z = sin(x2+y)
new(x, x2, y, z)
end
end

# Float64 타입으로 생성합니다.
println(MyData2{Float64}(2.0,3.0))
# MyData2{Float64}(2.0, 4.0, 3.0, 0.6569865987187891)

# Int 타입으로 생성합니다.
println(MyData2{Int}(2,3))
# MyData2{Int64}(2, 4, 3, 0.6569865987187891)






Mutable 타입 예제

 

Mutable  타입을 정의한 모듈 내의 함수 간에 데이터를 공유하는 예제 코드입니다. 

 

module TestModuleTypes

# 모듈 외부에서 모듈 이름 없이도 접근할 수 있도록 export로 선언합니다.
export Circle, computePerimeter, computeArea, printCircleEquation

# mutable 타입으로 정의된 Circle의 radius, perimeter, area는 갑 변경이 가능해집니다.
mutable struct Circle{T<:Real}
radius::T
perimeter::Float64
area::Float64

    # Circle 타입의 초기값을 설정합니다.
function Circle{T}(radius::T) where T<:Real
new(radius, -1.0, -1.0)
end
end

# 원의 둘레길이를 구합니다.
function computePerimeter(circle::Circle)
circle.perimeter = 2*π*circle.radius
# return circle.perimeter
end

# 원의 넓이를 구합니다.
function computeArea(circle::Circle)
circle.area = π*circle.radius^2
# return circle.area
end

# 원의 공식을 출력합니다.
function printCircleEquation(xc::Real, yc::Real, circle::Circle )
println("(x - $xc)^2 + (y - $yc)^2 = $(circle.radius^2)")
# return
end
end # end module



using .TestModuleTypes

# Circle 타입의 인스턴스를 생성합니다.
circle1 = Circle{Float64}(5.0)

# 원의 둘레길이를 구하고 출력합니다.
computePerimeter(circle1)
println(circle1.perimeter)
# 31.41592653589793

# 원의 넓이를 구하고 출력합니다.
computeArea(circle1)
println(circle1.area)
# 78.53981633974483

# 원의 공식을 출력합니다.
printCircleEquation(2, 3, circle1)
# (x - 2)^2 + (y - 3)^2 = 25.0






반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts