Reputation: 10709
Is there scala equivalent of python __getattr__ / __setattr__
(and other __*__
methods?). Some thing built-in or maybe some traits?
Upvotes: 4
Views: 1481
Reputation: 67888
For __getattr__
and __setattr__
you’ll have to wait until someone with more insight describes the new Scala 2.10 reflection API. (And of course: it won’t be directly translatable ever. It depends completely on your use case. If you just want a dynamic class, there will be a Dynamic
trait in the future; if you just want a tiny bit of that, then designing around pattern matching may be an obvious choice.)
As for the multitude of other __*__
methods in Python:
__call__
→ apply()
// pretty much identical in behaviour__metaclass__
// use case dependent:
class
inheritance or trait
mixins may be usefulsuper()
; in Scala super()
is always called in the constructor.__repr__
, __str__
→ toString()
__eq__
→ equals()
__init__
// implicitly called in the class body__new__
// not directly existent; depending on use case early initialisation __del__
// missing__nonzero__
// not really, except implicit def toBool[MyType](a: MyType): Boolean = ...
__len__
⇝ length
, size
or whatever is the convention in the container__getitem__
→ apply(i: IndexType)
// containers are functions in Scala__setitem__
→ update(i: IndexType, v: ValueType)
__delitem__
// no special handling needed; container convention__iter__
→ foreach(block: ValueType => Unit)
// with return value: map
, flatMap
Notably, apply
and update
are special in Scala, just as their Python counterparts. They allow for the following Syntax:
val x = collection(elem) // val x = collection.apply(elem)
collection(elem) = y // collection.update(elem, y)
Similarly, just as Python’s __iter__
allows a syntax like (el for el in container)
foreach
and map
make it possible to say for (el <- container) yield el
.
generally no special handling needed as we are allowed to define those directly:
__add__
, __sub__
, … // just define def + (arg: T)
or def - (arg: T)
this also includes comparison operators
__lt__
, __ge__
→ def <(other: T)
, def <=(other: T)
however, just as in Python, there are some special cases in the compiler for advanced things:
__radd__
, __rsub__
, … // right-associative operators; approx. def +: (arg: T)
or def -: (arg: T)
(append a :
)__iadd__
, __isub__
, … // modifying operators: def += (arg: T)
, …__enter__
, __exit__
// in most cases, a function argument fulfills the same purposeSee also: List of Scala's "magic" functions
Upvotes: 11
Reputation: 297265
I'm not sure what's the point here. Scala's uniform access principle means "fields" and methods share the same interface -- because, in fact, "fields" in Scala are getters and setters.
In other words, you can replace them like this:
var x: Int = 0
private[this] var _x = 0
def x = _x
def x_=(n: Int) { _x = n }
The getter and setter methods will control access to the private field you declared.
Now, if all you want is a way to provide non-static fields, you have to look at the Dynamic trait. It's experimental up to 2.9.2, but it will be available on 2.10, though behind a flag to warn people that this feature is dangerous (because it introduces dynamic typing, but if you don't think dynamic typing is dangerous, you should be fine).
Upvotes: 2