# Abstract constructor

**URL:** <https://discourse.julialang.org/t/abstract-constructor/29700>\
**Category:** General Usage\
**Created:** [October 9, 2019, 9:33pm UTC](https://discourse.julialang.org/t/abstract-constructor/29700 "2019-10-09T21:33:47Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [October 9, 2019, 9:33pm UTC](https://discourse.julialang.org/t/abstract-constructor/29700/1 "2019-10-09T21:33:47Z")

</div>

I have a set of types that are related, e.g. by composition, but also logically (eg one can be converted to another).

I have a parallel set of types that satisfy the same relations.

I’d like to put as much as possible in an abstract interface. Here is an example:

```julia
abstract type AbstractT1 end
abstract type AbstractT2 end

struct A1 <: AbstractT1
    x::Int
end

struct A2 <: AbstractT2
    a1::A1
end

struct B1 <: AbstractT1
    x::Int
end

struct B2 <: AbstractT2
    b1::B1
end

outer_type(::Type{A1}) = A2
outer_type(::Type{B1}) = B2

function double_T2(t1::T) where {T <: AbstractT1}
   return outer_type(T)(T(2 * t1.x))
end

```

```julia
julia> double_T2(A1(2))
A2(A1(4))

julia> double_T2(B1(3))
B2(B1(6))

```

In my actual use case, there are more types with more complex realtionships in each set. There are also more than two sets. I am currently using more functions like `outer_type`.

Something tells me that I am missing a more elegant way to do this. Has anyone run into this before ?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [October 10, 2019, 5:55am UTC](https://discourse.julialang.org/t/abstract-constructor/29700/2 "2019-10-10T05:55:55Z")

</div>

I guess you could encode the information provided by `outer_type` & friends in type parameters, eg

```julia
struct B1 <: AbstractT2{B2}

```

but I actually find methods more flexible so I would do it like you do above, even at the expense of a bit more code. If that becomes too repetitive, consider a macro.
