You can do pretty traditional OOP in Nim if you want to (except for proper 
abstract methods). Here's an example:
    
    
    # main.nim
    
    # Free Public License 1.0.0
    #
    # Permission to use, copy, modify, and/or distribute this software for
    # any purpose with or without fee is hereby granted.
    #
    # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
    # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
    # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
    # AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
    # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
    # PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
    # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    # PERFORMANCE OF THIS SOFTWARE.
    
    import oop, math
    
    {.this:self.}
    
    type
      Shape = ref object {.inheritable.}
      Circle = ref object of Shape
        radius: float
      Square = ref object of Shape
        width: float
      Rectangle = ref object of Shape
        width, height: float
    
    # Base methods
    
    method area(self: Shape): float {.base.} = abstract
    method circumference(self: Shape): float {.base.} = abstract
    method `$`(self: Shape): string {.base.} = abstract
    
    # Circles
    
    proc init(self: Circle, r: float) =
      radius = r
    method area(self: Circle): float =
      radius * radius * PI
    method circumference(self: Circle): float =
      radius * PI * 2
    method `$`(self: Circle): string =
      "Circle(" & $radius & $ ")"
    
    # Squares
    
    proc init(self: Square, w: float) =
      width = w
    method area(self: Square): float =
      width * width
    method circumference(self: Square): float =
      width * 4
    method `$`(self: Square): string =
      "Square(" & $width & $ ")"
    
    # Rectangles
    
    proc init(self: Rectangle, w, h: float) =
      width = w
      height = h
    method area(self: Rectangle): float =
      width * height
    method circumference(self: Rectangle): float =
      width * 2 + height * 2
    method `$`(self: Rectangle): string =
      "Rectangle(" & $width & ", " & $height & $ ")"
    
    proc main =
      let shapes = @[
        make Circle(3.0),
        make Square(5.0),
        make Rectangle(6.0, 4.5)
      ]
      for shape in shapes:
        echo shape
        echo "=> area ", shape.area
        echo "=> circumference ", shape.circumference
    
    main()
    
    
    
    # oop.nim
    
    # Free Public License 1.0.0
    #
    # Permission to use, copy, modify, and/or distribute this software for
    # any purpose with or without fee is hereby granted.
    #
    # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
    # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
    # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
    # AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
    # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
    # PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
    # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    # PERFORMANCE OF THIS SOFTWARE.
    
    import macros
    
    type AbstractMethodError* = object of Exception
    
    template abstract* =
      raise newException(AbstractMethodError, "abstract method")
    
    macro make*(e: untyped): auto =
      var tp, call: NimNode
      let sym = genSym(nskVar)
      case e.kind
      of nnkCall:
        case e[0].kind
        of nnkDotExpr:
          tp = e[0][0]
          call = newCall(e[0][1])
          add(call, sym)
          for i in 1..len(e)-1:
            add(call, e[i])
        of nnkIdent:
          tp = e[0]
          call = newCall(!"init", sym)
          for i in 1..len(e)-1:
            add(call, e[i])
        else:
          error("not a constructor call")
      of nnkDotExpr:
        tp = e[0]
        call = newCall(e[1], sym)
      else:
        error("not a constructor call")
      expectKind(tp, nnkIdent)
      result = quote do:
        var `sym` = `tp`()
        `call`
        `sym`
    
    when isMainModule:
      import strutils
      
      type Obj = ref object {.inheritable.}
        x: int
      
      type Obj2 = ref object of Obj
        y: int
      
      proc init(ob: Obj) =
        ob.x = 1
      
      proc init(ob: Obj, z: int) =
        ob.x = z
      
      proc fromString(ob: Obj, s: string) =
        ob.x = s.parseInt
      
      proc fromMin(ob: Obj, a, b: int) =
        ob.x = min(a, b)
      
      proc fromPair(ob: Obj2, pair: (int, int)) =
        ob.x = pair[0]
        ob.y = pair[1]
      
      proc `$`(ob: Obj): string = "Obj(x: " & $ob.x & ")"
      proc `$`(ob: Obj2): string = "Obj2(x: " & $ob.x & ", y: " & $ob.y & ")"
      
      var a1 = make Obj.init
      var a2 = make Obj.init(2)
      var a3 = make Obj(3)
      var a4 = make Obj.fromString("99")
      var a5 = make Obj.fromMin(314, 2718)
      var a6 = make Obj()
      var a7 = make Obj2.init()
      var a8 = make Obj2.fromString("314")
      var a9 = make Obj2.fromPair((10, 20))
      
      echo a1
      echo a2
      echo a3
      echo a4
      echo a5
      echo a6
      echo a7
      echo a8
      echo a9
    

Reply via email to