Yet another programmers blog

The new experiences of a new programmer

Maven – Building a Java-Groovy mixed project

without comments

I have a project that mixes Java and Groovy, and the main problem I ran into was that the jar was nicely built – but it only contained the Java classes, and none of the groovy ones.

When I ran the groovy compilation plugin, I got only the Groovy classes, and none of the Java ones…

So, what you need to do to compile both of them and have a normally built jar it this:

In your pom file, after all the dependencies and properties, just add this build section:


  src/main/groovy
  src/test/groovy
  
    
      ${project.basedir}/src/main/resources
    
  
  
    
      org.codehaus.gmaven
      gmaven-plugin
      ${gmaven-version}
      
        
          compile-groovy-classes
          
            compile
          
          compile
          
            
              
                
                ${project.basedir}/src/main/groovy
                
                  **/*.groovy
                
              
            
          
        
        
          compile-groovy-tests
          
            testCompile
          
          test-compile
          
            
              
                
                ${project.basedir}/src/test/groovy
                
                  **/*.groovy
                
              
            
          
        
      
      
        1.7
        
      
      
        
          org.codehaus.gmaven.runtime
          gmaven-runtime-1.7
          ${gmaven-version}
          
            
              org.codehaus.groovy
              groovy-all
            
          
        
        
          org.codehaus.groovy
          groovy-all
          ${groovy-version}
        
      
    
    
      org.apache.maven.plugins
      maven-surefire-plugin
      2.8.1
      
        true
        true
        plain
        true
      
    
  

Written by yossale

May 21st, 2012 at 4:48 pm

Posted in Frameworks,Java

Tagged with ,

XMLing in Java? Use java-xmlbuilder

without comments

XML is not native to Java. Many will disagree, but this is just the simple truth. It’s tedious, messy and generally ugly – specially compares to Groovy or Scala.

However, if you DO need to use XML in Java, do yourself a favour and use java-xmlbuilder.  I’ve tried it on easy-weight tasks, and it’s by far the simplest most straight-forward XML tool for Java I’ve used so far.

Enjoy!

Written by yossale

February 16th, 2012 at 4:53 pm

Posted in Frameworks,Java,Programming

Tagged with ,

Beware of Doubles, Floats, and generally floating points…

without comments

I’ve recently encountered few people who were naive about the representations of real (i.e not integers) numbers in computer languages , like double and float in Java (and their counterparts in other languages).

Since examples are worth much more then explanations, lets looks at this:

double y = 0.082;
double z = 8.2;

System.out.println("" + y +" * 100 = " + z + "? " +
                        (100 * y == z) + " it equals " + (100 * y) );

and the output is:
0.082 * 100 = 8.2? false it equals 8.200000000000001

The next example shows exactly why you should be wary of floating points. Look at the binary representation after each iteration.

public static void main(String[] args) {
  Double x = 1.0 / 3.0;
  for (int i=0; i= 1) {
    System.out.println("Iteration: " + i + " x = " + x);
    System.out.println("Binary representation: " + 
             Long.toBinaryString(Double.doubleToRawLongBits(x)));
    x = x * 2;
    if (x >= 1) {
      x = x - 1;
    }    
  }
}

Iteration: 0 x = 0.3333333333333333
Binary representation: 11111111010101010101010101010101010101010101010101010101010101
Iteration: 1 x = 0.6666666666666666
Binary representation: 11111111100101010101010101010101010101010101010101010101010101
Iteration: 2 x = 0.33333333333333326
Binary representation: 11111111010101010101010101010101010101010101010101010101010100
Iteration: 3 x = 0.6666666666666665
Binary representation: 11111111100101010101010101010101010101010101010101010101010100
Iteration: 4 x = 0.33333333333333304
Binary representation: 11111111010101010101010101010101010101010101010101010101010000
Iteration: 5 x = 0.6666666666666661
Binary representation: 11111111100101010101010101010101010101010101010101010101010000
Iteration: 6 x = 0.33333333333333215
Binary representation: 11111111010101010101010101010101010101010101010101010101000000
Iteration: 7 x = 0.6666666666666643
Binary representation: 11111111100101010101010101010101010101010101010101010101000000
Iteration: 8 x = 0.3333333333333286
Binary representation: 11111111010101010101010101010101010101010101010101010100000000
Iteration: 9 x = 0.6666666666666572
Binary representation: 11111111100101010101010101010101010101010101010101010100000000
Iteration: 10 x = 0.3333333333333144
Binary representation: 11111111010101010101010101010101010101010101010101010000000000
Iteration: 11 x = 0.6666666666666288
Binary representation: 11111111100101010101010101010101010101010101010101010000000000
Iteration: 12 x = 0.33333333333325754
Binary representation: 11111111010101010101010101010101010101010101010101000000000000
Iteration: 13 x = 0.6666666666665151
Binary representation: 11111111100101010101010101010101010101010101010101000000000000
Iteration: 14 x = 0.33333333333303017
Binary representation: 11111111010101010101010101010101010101010101010100000000000000
Iteration: 15 x = 0.6666666666660603
Binary representation: 11111111100101010101010101010101010101010101010100000000000000
Iteration: 16 x = 0.3333333333321207
Binary representation: 11111111010101010101010101010101010101010101010000000000000000
Iteration: 17 x = 0.6666666666642413
Binary representation: 11111111100101010101010101010101010101010101010000000000000000
Iteration: 18 x = 0.3333333333284827
Binary representation: 11111111010101010101010101010101010101010101000000000000000000
Iteration: 19 x = 0.6666666666569654
Binary representation: 11111111100101010101010101010101010101010101000000000000000000
Iteration: 20 x = 0.3333333333139308
Binary representation: 11111111010101010101010101010101010101010100000000000000000000
Iteration: 21 x = 0.6666666666278616
Binary representation: 11111111100101010101010101010101010101010100000000000000000000
Iteration: 22 x = 0.3333333332557231
Binary representation: 11111111010101010101010101010101010101010000000000000000000000
Iteration: 23 x = 0.6666666665114462
Binary representation: 11111111100101010101010101010101010101010000000000000000000000
Iteration: 24 x = 0.3333333330228925
Binary representation: 11111111010101010101010101010101010101000000000000000000000000
Iteration: 25 x = 0.666666666045785
Binary representation: 11111111100101010101010101010101010101000000000000000000000000
Iteration: 26 x = 0.3333333320915699
Binary representation: 11111111010101010101010101010101010100000000000000000000000000
Iteration: 27 x = 0.6666666641831398
Binary representation: 11111111100101010101010101010101010100000000000000000000000000
Iteration: 28 x = 0.3333333283662796
Binary representation: 11111111010101010101010101010101010000000000000000000000000000
Iteration: 29 x = 0.6666666567325592
Binary representation: 11111111100101010101010101010101010000000000000000000000000000
Iteration: 30 x = 0.3333333134651184
Binary representation: 11111111010101010101010101010101000000000000000000000000000000
Iteration: 31 x = 0.6666666269302368
Binary representation: 11111111100101010101010101010101000000000000000000000000000000
Iteration: 32 x = 0.33333325386047363
Binary representation: 11111111010101010101010101010100000000000000000000000000000000
Iteration: 33 x = 0.6666665077209473
Binary representation: 11111111100101010101010101010100000000000000000000000000000000
Iteration: 34 x = 0.33333301544189453
Binary representation: 11111111010101010101010101010000000000000000000000000000000000
Iteration: 35 x = 0.6666660308837891
Binary representation: 11111111100101010101010101010000000000000000000000000000000000
Iteration: 36 x = 0.3333320617675781
Binary representation: 11111111010101010101010101000000000000000000000000000000000000
Iteration: 37 x = 0.6666641235351562
Binary representation: 11111111100101010101010101000000000000000000000000000000000000
Iteration: 38 x = 0.3333282470703125
Binary representation: 11111111010101010101010100000000000000000000000000000000000000
Iteration: 39 x = 0.666656494140625
Binary representation: 11111111100101010101010100000000000000000000000000000000000000
Iteration: 40 x = 0.33331298828125
Binary representation: 11111111010101010101010000000000000000000000000000000000000000
Iteration: 41 x = 0.6666259765625
Binary representation: 11111111100101010101010000000000000000000000000000000000000000
Iteration: 42 x = 0.333251953125
Binary representation: 11111111010101010101000000000000000000000000000000000000000000
Iteration: 43 x = 0.66650390625
Binary representation: 11111111100101010101000000000000000000000000000000000000000000
Iteration: 44 x = 0.3330078125
Binary representation: 11111111010101010100000000000000000000000000000000000000000000
Iteration: 45 x = 0.666015625
Binary representation: 11111111100101010100000000000000000000000000000000000000000000
Iteration: 46 x = 0.33203125
Binary representation: 11111111010101010000000000000000000000000000000000000000000000
Iteration: 47 x = 0.6640625
Binary representation: 11111111100101010000000000000000000000000000000000000000000000
Iteration: 48 x = 0.328125
Binary representation: 11111111010101000000000000000000000000000000000000000000000000
Iteration: 49 x = 0.65625
Binary representation: 11111111100101000000000000000000000000000000000000000000000000
Iteration: 50 x = 0.3125
Binary representation: 11111111010100000000000000000000000000000000000000000000000000
Iteration: 51 x = 0.625
Binary representation: 11111111100100000000000000000000000000000000000000000000000000
Iteration: 52 x = 0.25
Binary representation: 11111111010000000000000000000000000000000000000000000000000000
Iteration: 53 x = 0.5
Binary representation: 11111111100000000000000000000000000000000000000000000000000000
Iteration: 54 x = 0.0
Binary representation: 0

Why does it happen?

Because if you use 64 bits to store a floating point number, you use 1 for the sign (+/-), 11 for the mantissa, and 52 for the value itself. And after adding 52 trailing zeroes …

In each deduction we remove the msb (most significan bit) and add a trailing 0 as a lsb (least significant bit) – and that’s – in a nutshell – what kills our precision. Naturally, there are ways to get over it, but you should be aware that you need to use these methods.

You can read more about it here:

http://kipirvine.com/asm/workbook/floating_tut.htm

http://support.microsoft.com/kb/42980

http://en.wikipedia.org/wiki/Single-precision_floating-point_format

Written by yossale

January 26th, 2012 at 5:51 pm

Posted in Uncategorized

Comparison method violates its general contract!

with 3 comments

java.lang.IllegalArgumentException: Comparison method violates its general contract!

Well, this is definitely the weirdest Java exception I’ve had so far. I got it on a Comparator I wrote, which returned either -1 or 1 (no == check was performed , and I never returned 0) .

This will happen to you usually when switching to Java 7 from older versions of Java. (Happened  to me when I switched from 6 to 7)

Long story short , the solution was to add the following line (Which is generally a good idea) to your Comparator :

if (o1 == o2) return 0;

Why does it happens ? Well, according to Java 7 change set, they replaced the merge sort implementation , and from now on

The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract.

 

Why is that important to them? I have no idea, but I’m guessing maybe the new merge sort works better when some elements are equal (i.e , the compartor returns 0), and having a “bad” comprator hinders performances. .

What I do fail to understand is why this contract validity test done on runtime and not on compilation time!

Written by yossale

December 8th, 2011 at 6:57 pm

Posted in Java,Programming

Concurrency in Java – Hashes, hashes of lists, ConcurrentHashMap, CopyOnWriteArrayList and Guava

without comments

 

This post is mainly about using hash and hash-like structures in a multi threaded app. You might want to consider reading about Callable and other approaches too.

First thing you should know about concurrency – it’s not simple. It’s never simple, and although the built-in structures might help you, you’ll still need to make sure that your solution is robust.

My problem was this: I needed to have a hash of String –> List<String> , and update the list. Something like this:

Map<String, List<String>> map = new HashMap<String, List<String>>();
for (Doc d : docs) {
  List<Doc> l = map.get(doc.getId());
  if (l == null) {
    l = new ArrayList<Doc>();
    map.put(doc.getId(),l);
  }
  l.add(d);
}

Naturally , this will only work in single threaded environment. But my environment is a multithreaded environment. So what do we do?

Well , the first, simplest solution is to just use  a SynchronizedMap. This will work, but it will slow down your application immensely – It’s basically wrapping your map with a lock, and limiting access based on the lock. Which is a good enough solution if speed is not an issue, but otherwise it’s a bit crippling.

The second simplest solution is to use ConcurrentMap. So we just replace our map with a ConcurrentHashMap.
We’ll ConcurrentHashMap is basically a map with a lot of locks (default is 16). That way, the buckets in the map are distributed to super-bucket themselves , and each super-bucket is protected via a lock. That way, you get much more access to the hash then in the Synchronized case.

Map<String, List<String>> map = new ConcurrentHashMap<String, List<String>>();
for (Doc d : docs) {
  List<Doc> l = map.get(doc.getId())
  if (l == null) {
    l = new ArrayList<Doc>()
    map.put(doc.getId(),l)
  }
  l.add(d)
}

However, we are still at risk of losing data due to a race condition: if we have 2 threaded that are trying to insert different document (d1, d2) with the same id to the hash in the same time , and the id is not yet there , then both of them might access the hash, see that there is value for that id, create a new, empty ArrayList, and then commit one right after the other – which means that we will lose one of the documents.

So, what do we do?

We’re going to use a very important function provided called “putIfAbsent”. It basically just does this :

if (!map.containsKey(key))
       return map.put(key, value);
   else
       return map.get(key);
but does it atomically. So if we’d change our code to reflect that :
Map<String, List<String>> map = new ConcurrentHashMap<String, List<String>>();
for (Doc d : docs) {

  List<Doc> l = new ArrayList<Doc>()
  List<Doc> cur = map.putIfAbsent(doc.getId(),l)

  if (cur == null) {
    l.add(d)
  } else {
    cur.add(d)
  }
}

What “putIfAbsent” returns is “what was in the list when I got there” . If it returns “null” , then the list we’ve provided , l, was placed in the hash a the value of our Id. Otherwise, there was already a list there, and we will have to use it (cur).

O.K, so that solves the problem of several threads overriding each other when creating a new list.

However, there’s a big chance that you’ll fail due to ConcurrentModificationException. Why is that?
The reason for that is because we are constantly changing the values in the ArrayList – and if you’re going to iterate over the list at that point or another while some threads are still working on it, you’re most definitely going to have ConcurrentModificationException.

So, what to do?

Well, I guess there are multiple ways to take care of it, but in my case , since the number of Docs per id is limited to few dozens, I choose to work with the CopyOnWriteArrayList . Basically what it does is this : every time you create an iterator of the list, the iterator has a “snapshot” of the list-state on the moment of it’s creation. That way, you will never have a  ConcurrentModificationException. So the new code is :

Map<String, CopyOnWriteArrayList<String>> map = new ConcurrentHashMap<String, CopyOnWriteArrayList<String>>();
for (Doc d : docs) {

    List<Doc> l = new CopyOnWriteArrayList <Doc>()
    List<Doc> cur = map.putIfAbsent(doc.getId(),l)

    if (cur == null) {
        l.add(d)
    } else {
        cur.add(d)
    }
}

Two last notes about concurrency in Java:

The first is that if you find yourself buried deep in concurrency issues, you might want to think about changing your strategy from synchronizing and concurrency to actors and callables.

The second is this – if you’re already creating specialized structures for your application – start thinking about using Guava - google’s open source concurrency package.

 

 

 

Written by yossale

November 17th, 2011 at 6:48 pm

Posted in Uncategorized

SearchIndexer & TSVNCache : Two things that are hogging your hd – and your computer

without comments

I have a brand new Lenovo T510 , i7, 4G ,64bit , Windows 7 with an Nvidia GPU – and it sucks. In this price , with these specifications , it really shouldn’t suck.
I’ve tried numerous things (including the regular defrag scan disk sequence) , and I did find a few problems (It was utilizing only 3 GB out of 4 , for example) – But it still sometimes had the worst performances ever.

I then noticed the my Hard drive icon is constantly flashing , even when I do no intense IO operations. It’s just always on. So I started searching for my HD hogger, and I found these two:

  • SearchIndexer.exe – This one is all MS fault. It’s the MS file indexer on Windows 7 . Now ,  I really like the new “look for a command name instead of  searching the damn thing in tens of application” , but why does it have to hog my HD all the time? It was accessing my hd ALL THE TIME! .
    This is how you make it go away. Basically , it’s a service , so you just run the services.msc and stop it (and then kill it from the task manager).
  • TSVNCache.exe – This one only applies if you use the Tortoise SVN client. (If you have no idea what this is , you probably don’t have it) . Apperantly , the Tortoise client really wants to be helpful , so it just keep scanning your entire hd to refresh the SVN icon on your files. This is such an over kill , as most of your folders aren’t managed by the svn. So this is how you make it stop crunching your hd , and only running where it should

 

My computer HD is now 90% lower on avg, and it actually feels like a good machine to have.

Written by yossale

April 27th, 2011 at 12:23 pm

Scala 101 – Named & Default parameters

without comments

Another syntax sugar provided in Scala are the default values for parameters , and the named parameters. Its fairly stright forwards , so We’ll just start with an example :

def f(age: Int, name: String = "MyName") = println ("Hello, " + name + " , you're "
                                                           + age + " years old")
f: (age: Int,name: String) Unit

scala> f (1)
Hello, MyName , you're 1 years old
scala> f (1,"Jaws")
Hello, Jaws , you're 1 years old

So we just gave the parameter a default value , and if we don’t provide a value , it just takes the default. That’s very nice. But what will happen in the following case?

def f(name: String = "MyName", age: Int) = println ("Hello, " + name + " , you're "  + age + " years old")
f: (name: String,age: Int) Unit

scala> f(1)
<console>:7: error: not enough arguments for method f: (name: String,age: Int)Unit.
Unspecified value parameter age.       
f(1)     

Well, this doesn’t work . Why? because the compiler can’t tell which argument you meant. One solution is to put all the default parameters at the end of the function:

def f(age: Int, name:String = "MyName") = println ("Hello, " + name + " , you're " + age + " years old")
f: (age: Int,name: String)Unit

scala> f(1)
Hello, MyName , you're 1 years old

Another , and better, option is to just call them by their names:

def f(name: String = "MyName", age: Int) = println ("Hello, " + name + " , you're "  + age + " years old")
f: (name: String,age: Int)Unit
scala> f(age=1)
Hello, MyName , you're 1 years old  

I feel like this entire thing is a syntactic sugar , but it’s still a nice one :)

Written by yossale

April 21st, 2011 at 1:49 pm

Posted in Programming,Scala

Tagged with

Scala 101 – Scoping

without comments

This is a part of my Scala tutorial . Read the first partsecond part for a more general Scala intro. You can read here for an overview of how to write a class in Scala.

Scoping

Like in most OO languages, you can limit the access to certain elements of the class (fields, methods) using access level modifiers – private , public , protected are the basic ones , but you can also have the package scope in Java , and the “friend” class in C++

Scala supports something much more agile then what we’ve come to expect  : As usual , you have private , protected and public (which is default in Scala , unlike in Java) – But , and this is where the fun begins , you also have a variable scope . Let’s see an example , as usual , with our Fish class:

Let’s say we have 2 fish : smallFish and bigFish. Currently , they can access each other’s private field “myName” :

 scala> var smallFish = new Fish("Small")
smallFish: Fish = Fish@5cb27de5
scala> var bigFish = new Fish("Big")
bigFish: Fish = Fish@78bdf2a

scala> bigFish.sayHello(smallFish)
hello, Small
scala> smallFish.sayHello(bigFish)
hello, Big

This is unavoidable in Java – The “private” modifier is valid for the class , not each object. It’s like a small community – everyone who is like you (i.e object of the same class) can access everything you have.

Let’s see how Scala solves this :

private[this] var myName = fishName

What we’ve done is added the “[this]” to the “private” access modifier – and that means that this variable is only usable from this object only. Let’s see what happens when we try to compile the class with this small change:

class Fish (var fishName: String){
   private[this] var myName = fishName
   def name = myName
   def name_= (newName: String) = myName = newName
   def sayHello(otherFish : Fish) = println ("hello, " + otherFish.myName)
}

<console>:11: error: value myName is not a member of Fish
def sayHello(otherFish : Fish) = println ("hello, " + otherFish.myName)

So the class won’t even compile – exactly like it won’t compile if you try to access a private field from outside the class.

What else can you write in the [scope] ?
Here is what Oreilly has to say about it :

Visibility is limited to [scope], which can be a package, type, or this (meaning the same instance, when applied to members, or the enclosing package, when applied to types).

 

Written by yossale

April 21st, 2011 at 12:10 am

Posted in Programming,Scala

Tagged with

Scala 101 – OOP : Getters & Setters

without comments

This is a part of my Scala tutorial . Read the first partsecond part for a more general Scala intro. You can read here for an overview of how to write a class in Scala.

Let’s say we have the following class:

class Fish {
   var name = "Default Name"
}

scala> var jaws = new Fish
jaws: Fish = Fish@8191a42
scala> jaws.name
res29: java.lang.String = Default Name
scala> jaws.name = "Jaws"
scala> jaws.name
res30: java.lang.String = Jaws

Now , let’s say you’ve decided you need to limit access to the name parameter vis a setter and a getter. How would those functions look like? Well , if you come from Java , like me , you would probably do something like this (after adding the “private” modifier to the variable):

And then you can use it like this:

scala> var jaws = new Fishjaws: Fish = Fish@1f619137
scala> jaws.getName
res32: java.lang.String = Default
scala> jaws.setName("Jaws")
scala> jaws.getName
res34: java.lang.String = Jaws

Problem Solved ? Well , this solution will work , but it’s crappy. Why is it crappy?

  • You broke your api
  • If you want to avoid breaking the api , you have to have getters/setters from step one – which is a lot of unnecessary code , and it’s really not very elegant.
  • It’s much less convenient then the previous way.

So here comes Scala to the rescue: First , lets change the field name from “name” to “myName”. Now , the Getter : lets create a function called “name” that will return the value of “myName”. It fairly easy:

//Getter
def name = myName

You don’t have to use “return” in Scala , and if it’s a one-liner , you can drop the {}  , so we get a lovely little function that we can use like this :

scala> jaws.name
res30: java.lang.String = Jaws

Now for the setter. What we would like to do is keep the convenient field access – if we can get the name by using “jaws.name” , it would be great if we could have a function that will enable us to do this :

 
jaws.name = "Jaws"
I bet you’re thinking “Yeah , and grandma can fly” . Well, she can! You see , in Scala , you can have a space in the name of the function. Let me repeat that  a space in the function name. So actually , we can write a function whose name is … “name =” . Stop looking a me like this, it works :) The magic little thing is , as always in Scala , _ . So this is our setter:
//Setter
def name_= (newName: String) = myName = newName
The _ stands for a space , and now we can have this class :

and we can do this:
scala> var jaws = new Fishjaws: Fish = Fish@8191a42
scala> jaws.name
res29: java.lang.String = Default Name
scala> jaws.name = "Jaws"
scala> jaws.name
res30: java.lang.String = Jaws
I knew you’d like it :)

Written by yossale

April 19th, 2011 at 10:21 pm

Posted in Programming,Scala,Uncategorized

Tagged with

Scala 101– Basic OOP : Writing a class

with one comment

This is part 3 of my Scala tutorial – read the first part and the second part for a more general Scala intro. All the examples you see here were ran via the REPL ( that’s the Scala interpreter).

Scala’s take on OOP:

Scala tends toward pure object oriented model:

  • There is no such thing as “primitive”.
    In Java , You have Objects and Primitives. Scala , on the other hand , takes after other language like Python, Ruby, Smalltalk (and many others) in the sense that Everything is an object. Including the integer 1 and string “Hello, World”. For many , this seems a reasonable evolution from the Object/Primitive dichotomy used in Java.
  • Functions and Closures are also Objects.
    This is something people with no background in functional programming sometimes find difficult to accept in the beginning.
    In Scala , a function is just another type of object , and as such it do anything an object can – Change , get sent as a parameter , be the return value of another function , and so forth. Even though the idea seems strange at first , you might recall that even in C/C++ you can pass a reference to a function , or use it as a return value from a function.
  • Operators are methods – Like in C++
  • Let’s get technical:

    Let’s build a simple class that will represent a fish. At first , a fish only has a name:

    scala> class Fish(var name: String) {}
    defined class Fish

    Well , something looks a bit… off… , isn’t it? There’s no constructor , no fields , no nothing! And yet , it works:

    scala> var jaws = new Fish("Jaws")
    jaws: Fish = Fish@530f243b
    
    scala> jaws.name
    res2: String = Jaws
    
    scala> jaws.name = "Rex"
    
    scala> jaws.name
    res3: String = Rex

    So what happened here , exactly? What we’ve used here is the “Primary Constructor”. The variable we’ve passed is a property of the class , and you really don’t need any more setters and getters.

    What if I want an immutable field? Just use “val” instead of “var” :

    scala> class Fish(val name: String) {}
    defined class Fish
    
    scala> var jaws = new Fish("Jaws")
    jaws: Fish = Fish@2876b359
    
    scala> jaws.name
    res4: String = Jaws
    
    scala> jaws.name = "Rex"
    <console>:7: error: reassignment to val
    jaws.name = "Rex"
    ^

    And private fields?

    scala> class Fish(private val name: String) {}
    defined class Fish
    
    scala> var jaws = new Fish("Jaws")
    jaws: Fish = Fish@15664f1a
    
    scala> jaws.name
    <console>:8: error: value name cannot be accessed in Fish
    jaws.name
    ^
    
    scala> jaws.name = "Rex"
    <console>:7: error: value name cannot be accessed in Fish
    jaws.name = "Rex"
    ^

    What about fields that aren’t in the constructor?

    scala> class Fish(val name: String) {
    val kind : String = "Shark"
    }
    defined class Fish
    
    scala> val f = new Fish("Jaws")
    f: Fish = Fish@69066caf
    
    scala> f.kind
    res12: String = Shark

    Well, that’s great , but I want more then one constructor!

    scala> class Fish(val name: String) {
    def this() = this("SomeName")
    }
    defined class Fish
    
    scala> var jaws = new Fish()
    jaws: Fish = Fish@1dd0eb0b
    
    scala> jaws.name
    res6: String = SomeName

    And something to tease you – How do you create a private primary constructor?

    scala> class Fish private (val name: String) {}
    defined class Fish
    
    scala> var jaws = new Fish("Jaws")
    <console>:6: error: constructor Animal cannot be accessed in object $iw
    var jaws = new Fish("Jaws")
    ^

    Scala has a primary constructor and zero or more auxiliary constructors. The primary constructor is the entire body of the class.  So actually , every line written in the body of the class will be executed (not including those inside functions / methods , naturally).
    Note: In Scala , any auxiliary constructor must call another constructor of the same class as it’s first actions!

    Let’s say we want a fish to print its name when it goes up:

     

    scala> class Fish(var name: String) {
    println(“I am “ + name)
    }
    defined class Fish
    
    scala> var jaws = new Fish("Jaws")
    I am Jaws

    The code line “println (“I am “ + name)” , although it appears context-less , is actually part of the constructor.

    Let’s sum everything up:

    class Fish(var name: String, private var age : Int) {
       println (“A new fish is born!”);
    
       //This is accessible
       val kind : String = "Shark"
    
       //This is not accessible
       private val nickName = "Goldi"
    
       def this() = {
          //An auxiliary con'r MUST invoke another constructor as it's first action!
          this("Fishi", 0)
          println ("I'm an auxiliary constructor!")
       }
    
       def this(name: String) = this(name, 0);
    
       def swim() = println("Blo Blo")
    
       private def showUpperFin() = println("Dramatic music!")
    
       //If you override a function , you must declare it using the override keyword. Unless the
       //function is abstract , and then it's kind of obvious to the compiler
       override def toString = "My name is " + name
    
       //An operator is a method just like any other
       def + (that: Fish): Fish = return new Fish(this.name,this.age + that.age)
    }

    So what have we learned so far?

    • Scala has a Primary constructor (which is the entire body of the class) and auxiliary constructors – which serve just like Java constructors.
    • The default Scala scope is public
    • You can declare class parameters in the primary constructor
    • You can access and change non private class properties by accessing them directly

    The next post will touch the getter/setters issue in Scala , limiting the scope of variables , using default values , and more . Stay tuned ;)

     

    Written by yossale

    April 16th, 2011 at 8:44 pm

    Posted in Programming,Scala

    Tagged with