4.6 KiB
Codon supports classes just like Python. However, you must declare class members and their types in the preamble of each class (like you would do with Python's dataclasses):
class Foo:
x: int
y: int
def __init__(self, x: int, y: int): # constructor
self.x, self.y = x, y
def method(self):
print(self.x, self.y)
f = Foo(1, 2)
f.method() # prints "1 2"
Unlike Python, Codon supports method overloading:
class Foo:
x: int
y: int
def __init__(self): # constructor
self.x, self.y = 0, 0
def __init__(self, x: int, y: int): # another constructor
self.x, self.y = x, y
def __init__(self, x: int, y: float): # yet another constructor
self.x, self.y = x, int(y)
def method(self: Foo):
print(self.x, self.y)
Foo().method() # prints "0 0"
Foo(1, 2).method() # prints "1 2"
Foo(1, 2.3).method() # prints "1 2"
Foo(1.1, 2.3).method() # error: there is no Foo.__init__(float, float)
Classes can also be generic:
class Container[T]:
elements: List[T]
def __init__(self, elements: List[T]):
self.elements = elements
Classes create objects that are passed by reference:
class Point:
x: int
y: int
p = Point(1, 2)
q = p # this is a reference!
p.x = 2
print((p.x, p.y), (q.x, q.y)) # (2, 2), (2, 2)
If you need to copy an object's contents, implement the __copy__
magic method and use q = copy(p)
instead.
Classes can inherit from other classes:
class NamedPoint(Point):
name: str
def __init__(self, x: int, y: int, name: str):
super().__init__(x, y)
self.name = name
{% hint style="warning" %} Currently, inheritance in Codon is static and polymorphism is not supported. {% endhint %}
Named tuples
Codon also supports pass-by-value types via the @tuple
annotation, which are
effectively named tuples (equivalent to Python's collections.namedtuple
):
@tuple
class Point:
x: int
y: int
p = Point(1, 2)
q = p # this is a copy!
print((p.x, p.y), (q.x, q.y)) # (1, 2), (1, 2)
However, named tuples are immutable. The following code will not compile:
p = Point(1, 2)
p.x = 2 # error: immutable type
You can also add methods to named tuples:
@tuple
class Point:
x: int
y: int
def __new__(): # named tuples are constructed via __new__, not __init__
return Point(0, 1)
def some_method(self):
return self.x + self.y
p = Point() # p is (0, 1)
print(p.some_method()) # 1
Type extensions
Suppose you have a class that lacks a method or an operator that might
be really useful. Codon provides an @extend
annotation that allows
programmers to add and modify methods of various types at compile time,
including built-in types like int
or str
. This actually allows much
of the functionality of built-in types to be implemented in Codon as type
extensions in the standard library.
class Foo:
...
f = Foo(...)
# We need foo.cool() but it does not exist... not a problem for Codon
@extend
class Foo:
def cool(self: Foo):
...
f.cool() # works!
# Let's add support for adding integers and strings:
@extend
class int:
def __add__(self: int, other: str):
return self + int(other)
print(5 + '4') # 9
Note that all type extensions are performed strictly at compile time and incur no runtime overhead.
Magic methods
Here is a list of useful magic methods that you might want to add and overload:
Magic method | Description |
---|---|
__copy__ |
copy-constructor for copy method |
__len__ |
for len method |
__bool__ |
for bool method and condition checking |
__getitem__ |
overload obj[key] |
__setitem__ |
overload obj[key] = value |
__delitem__ |
overload del obj[key] |
__iter__ |
support iterating over the object |
__repr__ |
support printing and str conversion |