1
0
mirror of https://github.com/exaloop/codon.git synced 2025-06-03 15:03:52 +08:00
codon/docs/language/classes.md
Ibrahim Numanagić 5de233a64e
Dynamic Polymorphism (#58)
* Use Static[] for static inheritance

* Support .seq extension

* Fix #36

* Polymorphic typechecking; vtables [wip]

* v-table dispatch [wip]

* vtable routing [wip; bug]

* vtable routing [MVP]

* Fix texts

* Add union type support

* Update FAQs

* Clarify

* Add BSL license

* Add makeUnion

* Add IR UnionType

* Update union representation in LLVM

* Update README

* Update README.md

* Update README

* Update README.md

* Add benchmarks

* Add more benchmarks and README

* Add primes benchmark

* Update benchmarks

* Fix cpp

* Clean up list

* Update faq.md

* Add binary trees benchmark

* Add fannkuch benchmark

* Fix paths

* Add PyPy

* Abort on fail

* More benchmarks

* Add cpp word_count

* Update set_partition cpp

* Add nbody cpp

* Add TAQ cpp; fix word_count timing

* Update CODEOWNERS

* Update README

* Update README.md

* Update CODEOWNERS

* Fix bench script

* Update binary_trees.cpp

* Update taq.cpp

* Fix primes benchmark

* Add mandelbrot benchmark

* Fix OpenMP init

* Add Module::unsafeGetUnionType

* UnionType [wip] [skip ci]

* Integrate IR unions and Union

* UnionType refactor [skip ci]

* Update README.md

* Update docs

* UnionType [wip] [skip ci]

* UnionType and automatic unions

* Add Slack

* Update faq.md

* Refactor types

* New error reporting [wip]

* New error reporting [wip]

* peglib updates [wip] [skip_ci]

* Fix parsing issues

* Fix parsing issues

* Fix error reporting issues

* Make sure random module matches Python

* Update releases.md

* Fix tests

* Fix #59

* Fix #57

* Fix #50

* Fix #49

* Fix #26; Fix #51; Fix #47; Fix #49

* Fix collection extension methods

* Fix #62

* Handle *args/**kwargs with Callable[]; Fix #43

* Fix #43

* Fix Ptr.__sub__; Fix polymorphism issues

* Add typeinfo

* clang-format

* Upgrade fmtlib to v9; Use CPM for fmtlib; format spec support; __format__ support

* Use CPM for semver and toml++

* Remove extension check

* Revamp str methods

* Update str.zfill

* Fix thunk crashes [wip] [skip_ci]

* Fix str.__reversed__

* Fix count_with_max

* Fix vtable memory allocation issues

* Add poly AST tests

* Use PDQsort when stability does not matter

* Fix dotted imports; Fix  issues

* Fix kwargs passing to Python

* Fix #61

* Fix #37

* Add isinstance support for unions; Union methods return Union type if different

* clang-format

* Nicely format error tracebacks

* Fix build issues; clang-format

* Fix OpenMP init

* Fix OpenMP init

* Update README.md

* Fix tests

* Update license [skip ci]

* Update license [ci skip]

* Add copyright header to all source files

* Fix super(); Fix error recovery in ClassStmt

* Clean up whitespace [ci skip]

* Use Python 3.9 on CI

* Print info in random test

* Fix single unions

* Update random_test.codon

* Fix polymorhic thunk instantiation

* Fix random test

* Add operator.attrgetter and operator.methodcaller

* Add code documentation

* Update documentation

* Update README.md

* Fix tests

* Fix random init

Co-authored-by: A. R. Shajii <ars@ars.me>
2022-12-04 19:45:21 -05:00

4.7 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 still under active development. Treat it as a beta feature. {% 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.

{% hint style="warning" %} Type extensions in Codon are also a beta feature. {% endhint %}

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