1. Composite Types
2. type unions
3. parametric type
4. type Alias
5. Constructors
6. Abstract

1. Composite Types
- Called records, structures or objects
- composite types are the most common form of user defined concrete type
- using ‘type’ keyword

```# Composite Types.
type foo
bar # If the type is not defined, then variable's defined as 'Any'
baz::Int
qux::Float64
end

super(foo) # -> Any
subtypes(foo) # -> 0-element Array{Any,1}

names(foo)

# 3-element Array{Any,1}:
# :bar
# :baz
# :qux

a = foo("hello Julia", 10, 3.14)
# foo("hello Julia",10,3.14)

a.bar
# "hello Julia"

a.baz
# 10

a.qux
# 3.14

replace( a.bar, "hello", "Hi" )
# "Hi Julia"

a
# foo("hello Julia",10,3.14)```

Immutable Composite Type: Immutable type instances of them cannot be modified.

```immutable Complex
real::Float64
imag::Float64
end

c = Complex(1.0, 2.0)
# Complex(1.0,2.0)

c.real = 1.5
ERROR: type Complex is immutable

julia> isimmutable(c)
# true
```

2. type unions

Immutable Composite Type / Type union
- A special abstract type which includes as objects all instances of any of its arguments type
- constructed using the special Union function

```julia> IntOrString = Union(Int, String)
# Union(Int64,String)

julia> a = 1::IntOrString
# 1

julia> b = "Hello"::IntOrString
"Hello"```

3. parametric type

Type parameters are introduced immediately after the type name, surrounded by curly braces.

```type Pair{T}
x::T
y::T
end

x = Pair(1,3)
# Pair{Int64}(1,3)

x = Pair( 1.0 , 3.5 )
# Pair{Float64}(1.0,3.5)

type Pair2{ T1, T2}
x::T1
y::T2
end

y = Pair2( 1, 3.14 )
# Pair2{Int64,Float64}(1,3.14)```
```type Point{T}
x::T
y::T
end

Point{Any} <: Point # true

Point{Any} <: Point{Float64} # false
# Concrete Point types with different values of T are never subtypes of each other

Point{Any} <: Point{Real} # false

a = Point{Float64}(1.0, 2.0)
# Point{Float64}(1.0,2.0)

# parameter of PointReal should be Real or subtype of Real
type PointReal{T <: Real}
x::T
y::T
end

PointReal{FloatingPoint}(1.0, 2.0)
# PointReal{FloatingPoint}(1.0,2.0)

PointReal{FloatingPoint}(1.0, 2.0im)
# ERROR: no method PointReal{FloatingPoint}(Float64,Complex{Float64})```

4. type Alias

```# Uint is different depending on 32/64bit system.
# 32-bit system;
Uint
# Uint32

# 64-bit system;
Uint
# Uint64

# is(a,b): check "a" and "b" are identical
if is(Int, Int64)
typealias Uint Uint64
else
typealias Uint Uint32
end

# Vector type: 1dim array
# Matrix type: 2dim array
typealias Vector{T} Array{T,1}
# Array{T,1}

typealias Matrix{T} Array{T,2}
# Array{T,2}
```

5. Constructors

```type OrderedPair
x::Real
y::Real
OrderedPair(x,y) = # inner Constructor. instances is generated using new(param)
x>y ? error("Out of order.") : new(x,y)
end

a = OrderedPair(1,2)
# OrderedPair(1,2)

b = OrderedPair(2,1)
# ERROR: Out of order.
#   in OrderedPair at none:5```

6. Abstract

Abstract types cannot be instantiated, and they are the backbone of the type system

```abstract Shape # definition of abstract type

##### type definition #####
type Triangle{T <: Real} <: Shape
x::T
y::T
Triangle(x,y) = x <= 0 || y <=0? error("x or y < 0 "): new(x,y)
end

type Square{T <: Real} <: Shape
x::T
y::T
Square(x,y) = x <= 0 || y <=0? error("x or y < 0 "): new(x,y)
end

type Circle{T <: Real} <: Shape
r::T
Circle(r) = r <= 0 ? error("r < 0 "): new(r)
end
##### type definition #####

##### function definition #####
function area( triange::Triangle)
return triangle.x * triangle.y / 2
end

function area( square::Square)
return square.x * square.y
end

function area( circle::Circle)
return circle.r^2 * pi
end
##### function definition #####

Triangle{Int64}(1,2)
Triangle{Float64}(3.0, 2.0)
Triangle{Float64}(1.2, -1) # ERROR: x or y < 0
# in Triangle at none:4

t = Triangle{Float64}( 1.0, 3.0 )s = Square{Float64}(2.0, 4.0)c = Circle{Float64}(5.4)
```