I'm trying to make it so I can get a value from one model into the creation of another model. This is very simplified but gives the error I'm having with a model instance extending a squeryl model. In reality I'm doing some calculations specific to this model, but need a value from another model.
I'm getting an error doing all sorts of versions of this:
class Bar(
val bazId: String
val someValue: String
) extends db.BaseModel {
val foo: Foo = db.MyDb.foos.lookup(bazId).head
def this(
bazId: Baz
) = {
this (
Baz.id,
foo.someValue,
)
}
The error is:
not found: value foo
[error] foo.someValue,
^
I've tried having some kind of lookup in the Object/singleton, inside of the def this() (that gives a "Application does not take parameters" error), and other things but nothing is working. Seems so simple, but having no luck at all.
The issue is you are trying to access a member of the class in the constructor, and since this is before the object has been constructed - it is not accessible. Doing it in the companion should help you get around that. Something like:
object Bar {
val foo(bazId:String): Foo = db.MyDb.foos.lookup(bazId).head
}
class Bar(
val bazId: String,
val someValue: String
) extends db.BaseModel {
val foo: Foo = Bar.foo(bazId)
def this(
bazId: String
) = {
this (
bazId,
Bar.foo(bazId).someValue
)
}
}
Or, if you did intend to have the constructor accept the class Baz, then you could also add the lookup method directly in Baz - then you can just call it directly to look up Foo.
Related
What is the difference between defining an object using the new operator vs defining a standalone object by extending the class?
More specifically, given the type class GenericType { ... }, what is the difference between val a = new GenericType and object a extends GenericType?
As a practical matter, object declarations are initialized with the same mechanism as new in the bytecode. However, there are quite a few differences:
object as singletons -- each belongs to a class of which only one instance exists;
object is lazily initialized -- they'll only be created/initialized when first referred to;
an object and a class (or trait) of the same name are companions;
methods defined on object generate static forwarders on the companion class;
members of the object can access private members of the companion class;
when searching for implicits, companion objects of relevant* classes or traits are looked into.
These are just some of the differences that I can think of right of the bat. There are probably others.
* What are the "relevant" classes or traits is a longer story -- look up questions on Stack Overflow that explain it if you are interested. Look at the wiki for the scala tag if you have trouble finding them.
object definition (whether it extends something or not) means singleton object creation.
scala> class GenericType
defined class GenericType
scala> val a = new GenericType
a: GenericType = GenericType#2d581156
scala> val a = new GenericType
a: GenericType = GenericType#71e7c512
scala> object genericObject extends GenericType
defined module genericObject
scala> val a = genericObject
a: genericObject.type = genericObject$#5549fe36
scala> val a = genericObject
a: genericObject.type = genericObject$#5549fe36
While object declarations have a different semantic than a new expression, a local object declaration is for all intents and purpose the same thing as a lazy val of the same name. Consider:
class Foo( name: String ) {
println(name+".new")
def doSomething( arg: Int ) {
println(name+".doSomething("+arg+")")
}
}
def bar( x: => Foo ) {
x.doSomething(1)
x.doSomething(2)
}
def test1() {
lazy val a = new Foo("a")
bar( a )
}
def test2() {
object b extends Foo("b")
bar( b )
}
test1 defines a as a lazy val initialized with a new instance of Foo, while test2 defines b as an object extending Foo.
In essence, both lazily create a new instance of Foo and give it a name (a/b).
You can try it in the REPL and verify that they both behave the same:
scala> test1()
a.new
a.doSomething(1)
a.doSomething(2)
scala> test2()
b.new
b.doSomething(1)
b.doSomething(2)
So despite the semantic differences between object and a lazy val (in particular the special treatment of object's by the language, as outlined by Daniel C. Sobral),
a lazy val can always be substituted with a corresponding object (not that it's a very good practice), and the same goes for a lazy val/object that is a member of a class/trait.
The main practical difference I can think of will be that the object has a more specific static type: b is of type b.type (which extends Foo) while a has exactly the type Foo.
I have two classes in a database, and wish to set up a one to many relation. Nothing complicated. However, I'm getting an assertion failure in squeryl's _splitEquality (on line 576). Squeryl is version 0.9.5
So I have a schema
object Tables extends Schema {
val foo = table[Foo]("foo_table")
val bar = table[Bar]("bar_table")
val fooBar = oneToManyRelation(foo,bar).via((f,b) => f.id === bar.foo_fk)
}
Where foo is
class Foo (val foo_id: String, val useful_info: String)
extends KeyedEntity[String] {
override def id: String = foo_id
}
and bar is
class bar (val foo_fk) {
def useful_info = Tables.fooBar.right(this).head.useful_info
}
However, this fails at runtime with the previously mentioned assertion failure, specifically that:
assert(ee.right._fieldMetaData.isIdFieldOfKeyedEntity)
fails
I fixed it by using a column annotation on Foo instead of overriding id.
So foo became
class Foo (
#Column("foo_id")
val id: String,
val useful_info: String)
extends KeyedEntity[String] {
}
I'm not totally sure why this worked, but I'm annoyed that it did.
Are there public instance variables anymore in Scala? I'm reading Programming in Scala, which covers Scala 2.8. If I'm understanding it correctly, it claims that vars in 2.8 are by default public.
I'm trying to write code for 2.9.1.final now, and instance variables are now by default private? But there's no public keyword that I'm aware of. (Interestingly enough, it appears it used to exist sometime in the 2.x series, but it mysteriously disappeared somewhere along the line.)
Am I missing something obvious?
Also, by extension, is there an easy way to declare a variable passed to a class constructor to be public (since it appears that those also have default private visibility now too)?
Example:
class Instance(label: String, attributes: Array[Int]){
val f = 0
}
Eclipse claims that label, attributes, and f are all private. Scala 2.9.1.final is being used as the library.
In scala, if you omit the modifer, then instance fields are public by default:
scala> class Foo { var foo = 1 }
defined class Foo
scala> class Bar { def bar() = { val f = new Foo; f.foo = 5; }}
defined class Bar
No worries there. However, when you use a variable in a constructor, the variable is not necessarily turned into a field:
scala> class Foo(foo: Int)
defined class Foo
scala> class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
<console>:8: error: value foo is not a member of Foo
class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
^
so you can declare it as a val or var to have it available:
scala> class Foo(val foo: Int)
defined class Foo
scala> class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
defined class Bar
Note that all fields are actually private, but scala exposes accessor methods (foo() and foo_=(t: Int)) to enable you to access the fields), which is why scala-ide says that the fields are private (assuming you mean when you hover over the variable).
I am learning lift and mongodb. I encountered a problem as following. I will bypass some code for simplicity. Here is the code:
object User extends User with MetaMegaProtoUser[User] {
}
class User extends MegaProtoUser[User] {
def meta = User
//record the post list that user like
object likePostList extends MongoListField[User, ObjectId](this)
def test()
{
val list: = this.likePostList
println(list.length)
}
}
error: value length is not a member of object User.this.likePostList
this.likePostList.length
I can store the ObjectId data in MongoDB. But the MongoListField does not return a list. Why? How to use it as a List.
I try to add type case it to List[OjbectId] or List[String] but without luck.
val list: List[ObjectId] = this.likePostList.asInstanceOf[List[Object]]
Got error:
java.lang.ClassCastException: com.cosiin.model.User$likePostList$ cannot be cast to scala.collection.immutable.List
I think I am using MongoListField the wrong way. But I do not know how to use it.
Can anyone help? Thanks
Fields you declare in Lift Records are field objects, not the actual values contained within the field. In order to access the actual value you need to call:
this.likePostList.get
or if the field is optional
this.likePostList.valueBox
which returns a scala.Option like object.
If you think of it, this makes very much sense because you're actually declaring likePostList to be an instance of MongoListField when you type:
object likePostList extends MongoListField[User, ObjectId](this)
as opposed to
val likePostList: List[ObjectId] = ...
there's no magic Scala can do to automatically convert that to List[ObjectId]. It's the same as:
class Foo {
val bar = 3
object baz { val greeting = "hello" }
}
val foo = new Foo
println(foo.bar) // prints 3
println(foo.baz) // prints something like Foo$baz$#1d981b6a
println(foo.baz.greeting) // prints "hello"
P.S. in older versions of Lift, get was called is.
I need access to the Class of the object being constructed in its own constructor (for various detailed reasons I don't think are relevant to my question).
I want something like this
class Foo(val i:Int)
class Bar extends Foo(this.getClass.getName.length)
val b = new Bar
println(b.i)
to print 3 ("Bar".length). But it doesn't. If the code above is inside some other object, "this" refers to that object. If the code above is not inside some other object (just in some package), the compiler complains with
error: this can be used only in a class, object, or template
class Bar extends Foo(this.getClass.getName)
^
CLARIFICATION: I can't change Foo to use a val in its body instead of its constructor because Foo's API already exists and is fixed (so, yes, i must be a constructor parameter). It needs an integer argument at constructor time, but that integer can only be calculated with access to the Class.
(I know the example above is still silly and degenerate. If people care, I can explain in detail why I need the class in my real project, http://code.google.com/p/factorie)
Surely, the class of the object being constructed is known to the compiler and runtime during construction. With what syntax can I get it? (Is there no such syntax? If not, I wonder why. I'm surprised it there doesn't seem to be a simple, standard way to get this.)
A lazy val solves this problem:
object Early
{
abstract class Foo { val name: String }
class Bar extends Foo { lazy val name = getClass.getName }
def
main(args: Array[String]): Unit = {
val b = new Bar
println(b.name)
}
}
Yields:
% scala Early
Early$Bar
Not sure whether this is possible in a clean way. If you like hacks you could do
class Bar extends Foo((new Exception).getStackTrace.apply(0).getClassName)
However I strongly advertise against it!
This appears to satisfy your requirement without using a lazy val and without altering the base class:
scala> class Base(val name: String)
defined class Base
scala> class Derived extends Base(classOf[Derived].getName)
defined class Derived
scala> new Derived name
res0: String = Derived
You are going to have to explain your motivation for wanting to do this. Does name have to be a constructor parameter of Foo or can it be an abstract member? Does it have to be a val or will a def do.
You can do this
class Foo(val name: String)
class Bar extends Foo("") {
override val name = getClass.getName
}
and new Bar().name will give Bar
But I suspect that if your true motivation is known then there is a better way to do what you really want.
How about
class Bar extends Foo(classOf[Bar].getName.length)
What about this:
class Foo(otherName: Option[String] = None) {
val name = otherName.getOrElse(this.getClass.getName)
}
class Bar extends Foo()
val b = new Bar
println(b.name)