noob question about val vs var in class definitions

86 views
Skip to first unread message

Sean Wolfe

unread,
May 12, 2015, 10:10:57 PM5/12/15
to scala...@googlegroups.com
Hello fellow Android and Scala fans !!

I'm working with Scala and a Java based game development framework called Libgdx. So far it's working -- I'm using SBT and have finished an initial port of a demo game. My work is here: https://github.com/SeanFelipe/libgdx-demo-pax-britannica-scala

Question -- I find myself in an unfortunate pattern which I'd like to get some feedback on. I want to set values only one time, but there are competing factors:

1. I must set values which are available across the class in the constructor
2. the android ecosystem won't initialize until onCreate, so I can't declare values until I get to onCreate.

Basically, I need onCreate to act as the constructor.

My current approach is to set them as vars with defaults in the constructor, then set them again in onCreate. I'd rather do it once and make them vals.

Any suggestions on a better pattern? Example code is below.

----------------------

class MyGame extends Game {

    var scalaImage : Texture = _
    var camera : OrthographicCamera = _
    var batch : SpriteBatch = _

    override def create() {
        scalaImage = new Texture(Gdx.files.internal("scala.png"))
        camera = new OrthographicCamera()
        camera.setToOrtho(false, 800, 480)
        batch = new SpriteBatch()
    }    

    override def render() {
        Gdx.gl.glClearColor(0, 0, 0.2f, 1)
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
        batch.setProjectionMatrix(camera.combined)
        batch.begin()
        batch.draw(scalaImage, 200, 200)
        batch.end()
    }

}

Som Snytt

unread,
May 12, 2015, 11:56:36 PM5/12/15
to Sean Wolfe, scala-user
A lazy val is initialized once, lazily.

To enforce that init is post-create, the initializer can throw if a flag isn't set.

lazy val image = if (created) new Texture else ???

A subsequent attempt to init can succeed. For example,

scala> var flag = false
flag: Boolean = false

scala> lazy val v = if (flag) 42 else ???
v: Int = <lazy>

scala> import util.Try
import util.Try

scala> Try(v)
res0: scala.util.Try[Int] = Failure(scala.NotImplementedError: an implementation is missing)

scala> flag = true
flag: Boolean = true

scala> Try(v)
res1: scala.util.Try[Int] = Success(42)



--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sean Felipe Wolfe

unread,
May 13, 2015, 1:59:28 AM5/13/15
to Som Snytt, scala-user
This is great - thanks !
--
A musician must make music, an artist must paint, a poet must write,
if he is to be ultimately at peace with himself.
- Abraham Maslow

Sean Wolfe

unread,
May 13, 2015, 2:08:07 AM5/13/15
to scala...@googlegroups.com, ethe...@gmail.com
Worked great! here is the updated code.

class Start extends Game {

    lazy val scalaImage = new Texture(Gdx.files.internal("scala.png"))
    lazy val camera = new OrthographicCamera()
    lazy val batch = new SpriteBatch()

    override def create() {
        camera.setToOrtho(false, 800, 480)

Nick Stanchenko

unread,
May 14, 2015, 3:54:45 PM5/14/15
to scala...@googlegroups.com
Note that when your Activity is recreated, you might want to recreate some of those things as well. In that case the “var” approach is the only way to go (although you can make it fancier by using Options).

Nick

Sean Wolfe

unread,
May 15, 2015, 1:56:21 PM5/15/15
to scala...@googlegroups.com
Ah good point. Will have to make sure I test pause and resume and oncreate/ondestroy.

I suppose in conventional Android Java, most of these variables don't get the 'final' keyword, so they're vars anyhow.

Thanks!

Nils Kilden-Pedersen

unread,
May 15, 2015, 2:37:58 PM5/15/15
to Nick Stanchenko, scala-user

On Thu, May 14, 2015 at 2:54 PM, Nick Stanchenko <nick....@gmail.com> wrote:

Note that when your Activity is recreated, you might want to recreate some of those things as well. In that case the “var” approach is the only way to go (although you can make it fancier by using Options).

Should those vars also be @volatile, or does Android handle that?


Nick


On Wednesday, May 13, 2015 at 7:08:07 AM UTC+1, Sean Wolfe wrote:
Worked great! here is the updated code.

class Start extends Game {

    lazy val scalaImage = new Texture(Gdx.files.internal("scala.png"))
    lazy val camera = new OrthographicCamera()
    lazy val batch = new SpriteBatch()

    override def create() {
        camera.setToOrtho(false, 800, 480)
    }

    override def render() {
        Gdx.gl.glClearColor(0, 0, 0.2f, 1)
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
        batch.setProjectionMatrix(camera.combined)
        batch.begin()
        batch.draw(scalaImage, 200, 200)
        batch.end()
    }
}

On Tuesday, May 12, 2015 at 8:56:36 PM UTC-7, som-snytt wrote:
A lazy val is initialized once, lazily.

To enforce that init is post-create, the initializer can throw if a flag isn't set.

lazy val image = if (created) new Texture else ???

Nick Stanchenko

unread,
May 15, 2015, 2:40:45 PM5/15/15
to scala...@googlegroups.com, nick....@gmail.com
In most cases they are only updated (and used) from the UI thread (this includes the onCreate, onStart, etc methods).

Nick

Sean Wolfe

unread,
May 15, 2015, 8:32:46 PM5/15/15
to scala...@googlegroups.com
I think it's a really interesting field - I'm able to make much more expressive code while leveraging a mature Java framework. Good times !

Dominik Bucher

unread,
May 16, 2015, 1:16:26 PM5/16/15
to scala...@googlegroups.com
Cool, love the Scala and libgdx combination! I did a lot of libgdx programming a while ago, with Java though. Just one remark from my experiences: If you intend to do a game that needs smooth redrawing (e.g., a  side scroller, but not a word game for example), you'll want to run garbage collection as little as possible (basically never). And as such immutable fields can be a pain as well (as the proper way to update an immutable field is basically to copy the object and change the field, which produces a lot of garbage). Think of updating your player sprite's position every 1/30 of a second.

Good thing is, with Scala you can mix immutable with mutable and get the best of both worlds :).

Dom

Sean Wolfe

unread,
May 18, 2015, 2:30:36 PM5/18/15
to scala...@googlegroups.com
Ah thanks a lot Dom -- I'll keep it in mind.
Reply all
Reply to author
Forward
0 new messages