Is there scala equivalent of python __getattr__ / __setattr__ (and other __*__ methods?). Some thing built-in or maybe some traits?
2 Answers
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:
Global things
__call__→apply()// pretty much identical in behaviour__metaclass__// use case dependent:- currently
classinheritance ortraitmixins may be useful - in many cases all that metaclass does is instance construction which avoids a call to
super(); in Scalasuper()is always called in the constructor.
- currently
__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, exceptimplicit def toBool[MyType](a: MyType): Boolean = ...
Container Types
__len__⇝length,sizeor 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.
Operators
generally no special handling needed as we are allowed to define those directly:
__add__,__sub__, … // just definedef + (arg: T)ordef - (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)ordef -: (arg: T)(append a:)__iadd__,__isub__, … // modifying operators:def += (arg: T), …
Context manager
__enter__,__exit__// in most cases, a function argument fulfills the same purpose
See also: List of Scala's "magic" functions
1 Comment
__getattr__ and __setattr__ are prominently missing?)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).
1 Comment
__getattr__ and __setattr__ are not directly related to the uniform access principle in Python (at least not since the property decorator has been established).
__*attr__()are used to control behavior when accessing an object's attributes.