0

I am new to Scala and wondering if I can somehow refactor this code using Scala's support for function literals, higher order functions etc

Because there is no relationship between a Competition and a Team, I don't see how this is possible. I guess I could add a trait to Competition and Team that would include the name property and it would then be possible.

Any other alternatives?

class CompetitionDao extends BaseDao[Competition]{

  def retrieveAllCompetitionNames(): java.util.List[String] = {
    val competitions: java.util.List[_ <: Competition] = getDao().queryForAll()
    val competitionNames: java.util.List[String] = new ArrayList();
    for (competition <- competitions) competitionNames.add(competition.name)
    competitionNames
  } 

}

class TeamDao extends BaseDao[Team]{

  def retrieveAllTeamNames(): java.util.List[String] = {
    val teams: java.util.List[_ <: Team] = getDao().queryForAll()
    val teamNames: java.util.List[String] = new ArrayList();
    for (team <- teams) teamNames.add(team.name)
    teamNames
  }  
}
DJ180
  • 18,724
  • 21
  • 66
  • 117
  • 1
    How about def retrieveAllXNames = getDao().queryForAll().map(_.name) ? – Enrique Mar 27 '13 at 02:21
  • Not sure that works, just tried it – DJ180 Mar 27 '13 at 03:40
  • There's a lot of code missing here. What is `getDao().quaryForAll()`? It's hard to understand what you're trying to achieve, but I agree with Enrique, this should be a one-liner with native Scala collections. Also, you can automatically convert between Scala and Java collections with `import scala.collection.JavaConversions._`. – Kipton Barros Mar 27 '13 at 04:54

2 Answers2

4

You could introduce a trait and use map like Enrique suggested:

import scala.collection.JavaConversions._

trait NameRetrieval[T <: { def name: String }] { self: BaseDao[T] =>
  def retrieveAllNames = getDao.queryForAll.map(_.name)
}

You can then use it like this:

object TeamDao extends BaseDao[Team] with NameRetrieval[Team]

Edit

The [T <: { def name:String }] means that the NameRetrieval trait can be used for any type that has a an element called name of type String. To find out more about that notation search for 'Scala structural types'.

With the self: BaseDao[T] I say that this trait can only be used in combination with a BaseDao that has the same type for T. This allows me to freely use the getDao method because I know for sure it's available. A similar pattern is used in the Cake Pattern, so you can check that out for more information.

Community
  • 1
  • 1
EECOLOR
  • 11,184
  • 3
  • 41
  • 75
  • that's quite elegant, i like that – fracca Mar 27 '13 at 13:00
  • Can you add some information on what {def name: String} does or what it is needed for? Likewise for the self variable – DJ180 Mar 27 '13 at 16:31
  • @DJ180 the term you need to search for is "structural type". Here it means "any T that has a `name` method returning a String". `self` is a "self type", which means the trait can only be mixed in to the specified type, thus making the members of that type available. Also, `JavaConversions` is semi-deprecated: use `JavaConverters` instead... although if you're actually trying to return a `java.util.List` be aware that this answer uses Scala collections, so it would be more efficient to use neither. – Luigi Plinge Mar 27 '13 at 17:11
0

You could try something like:

object DAO{
  def getNames: String => List[String] = { from =>
    from match {
      case "competition" => Competition.getDao().queryForAll().map(_.name)
      case "team" => Team.getDao().queryForAll().map(_.name)
    }
  }

  ...
}

calling this would be as easy as

val temNames : List[String] = DAO.getNames("team")
korefn
  • 955
  • 6
  • 17