Upon digging it seems this is a sensitive issue.
class TestNames {
private[this] lazy val _name: String = this.getClass.getName.split("\\.").last
def name: String = _name
}
class Parent extends TestNames
class Parent2 extends Parent
class ClassNameExtraction extends FlatSpec {
it should "correctly extract the table name" in {
object TestNames extends TestNames
assert(TestNames.name === "TestNames")
}
it should "correctly extract the parent name" in {
object Parent extends Parent
assert(Parent.name === "Parent")
}
it should "correctly extract the column names" in {
object Parent2 extends Parent2
assert((Parent2.name === "Parent2"))
}
}
I can see there is a simple pattern: $$annonfun$number$ + ACTUAL_CLASS_NAME + $number$.
Is there a simpler way of doing this?
Update:
Got something working without inheritance:
import scala.reflect.ClassTag
class SomeClass {
private[this] lazy val _name: String = implicitly[ClassTag[this.type]].runtimeClass.getSimpleName
def name: String = _name
}
However this returns the same name in sub classes:
class SomeOtherClass extends SomeClass {}
object SomeOtherClass extends SomeOtherClass
SomeOtherClass.name// is still SomeClass
There is an issue:
https://issues.scala-lang.org/browse/SI-2034
Do you need a class per se or a type name? Because that's what reflection is for.
The policy is not to discuss religion, politics or name mangling.
Related
I thought putting final in Function would stop this issue from happening? I'm not too familiar with Scala. Can someone explain?
Class 'Country must either be declared abstract or implement abstract member 'execute():Object' in path.to.Invokable'
class Country extends MarketFunction("america") {}
abstract class MarketFunction(function: String) extends Function {
...
}
trait Function extends Invokable {
final def execute(): AnyRef = {
// not important
}
}
public interface Invokable {
Object execute();
}
Is it because AnyRef is not a direct comparison to java Object?
This worked for me
class Country extends MarketFunction("america") {}
abstract class MarketFunction(function: String) extends Function[AnyRef] {
...
}
trait Function[A <: AnyRef] extends Invokable {
override final def execute(): A = {
// not important
}
}
public interface Invokable {
Object execute();
}
//File Animal.scala
abstract class Animal {
val name: String
def getSomething(tClass: TypeClass): String = {
tClass.tName.split('.').lift(0)
}
def apply(tClass: TypeClass): SomeOtherClassType = {
// something...
}
// File: DogSpike, this is used for some specific cases (overwrites
base class val)
object DogSpike extends Animal {
override val name: String = "Spike"
}
this call then works (calls apply)
myTransformation(() => DogSpike(this))
Now I would like to create a more generic object that one can pass arguments but I am unable to.
It would work to create a derived Object from Animal that takes one arguments and being able to use the apply call
object TheDog(name: String) extends Animal {
override val name: String = "Spike"
//...
}
not sure how to implicitly call Animal.apply for TheDog object where I could pass a parameter (name)
myTransformation(() => TheDog(this))
// also this seems to be incorrect "*Wrong top statement declaration*"
object TheDog(val n: String) extends Animal {
override val name: String = n
//...
}
As of *Wrong top statement declaration* (I can understand only this part of your question) - you can't have constructor in object as object is a singleton, so you should use a case class (ADT):
final case class TheDog(name: String) extends Animal
scala>TheDog("Spike")
res2_2: TheDog = TheDog("Spike")
val and companion object with apply is added automatically for case classes, so you don't need to define your own own apply in Animal. case class TheDog(val name: String) is same as case class TheDog(name: String).
I's also use traits instead of abstract class:
trait Animal {
val name: String
def getSomething: String = {
"Dog: " + name
}
}
I don't understand your TypeClass type, but if you really want type classes:
trait Animal {
def name: String
}
final case class TheDog(name: String) extends Animal
final case class TheCat(name: String) extends Animal
implicit class RichDog(dog: TheDog){
def getSomething: String = {
"Dog" + dog.name
}
}
implicit class RichCat(cat: TheCat){
def getSomething: String = {
"Cat: " + cat.name
}
}
scala> TheDog("Spike").getSomething
res4_5: String = "DogSpike"
scala> TheCat("Tom").getSomething
res4_6: String = "Cat: Tom"
About calling apply "implicitly", I don't know why would anyone need this, but:
trait AnimalFactory[A <: Animal] {
def apply(name: String)(implicit constructor: String => A) = constructor(name)
}
object TheeeDog extends AnimalFactory[TheDog]
implicit def createDog(name: String) = TheDog(name)
TheeeDog("Spike")
Of course you have to provide createDog and make it visible for a client, but it doesn't really make sense if you can just use ADTs and define additional required applys in companion object:
case class TheMouse(name: String)
object TheMouse{
def apply(isJerry: Boolean): TheMouse = if (isJerry) TheMouse("Jerry") else TheMouse("NotJerry")
}
TheMouse(true)
If you want to add some parameter to constructor, just add it:
class AnimalFactory(clazz: SomeClass){
def doSomething = clazz.name
def apply(name: String)
}
val dogFactory = new AnimalFactory(dogClassDescriptor)
val catFactory = new AnimalFactory(catClassDescriptor)
dogFactory("Spike")
catFactory("Tom")
You can even create a factory for factory (I wouldn't recommend - this solution already looks overcomplicated):
object AnimalFactory{ //please don't use classes for that - avoiding `new` is not their purpose
def apply(clazz: SomeClass) = new AnimalFactory(clazz)
}
val dogFactory = AnimalFactory(dogClassDescriptor)
//or even `val spike = AnimalFactory(dogClassDescriptor)("Spike")`
But still what's the point if you could just provide underlying clazz either as a member or just in a wrapper:
final case class ClazzWrapper[T <: Animal](clazz: SomeClass, animal: T)
In Scala, how can I extend a trait in a class with private constructor parameter that is defined in the trait?
trait Parent {
protected def name: String
require(name != "", "wooo problem!")
}
class Child(private val name: String) extends Parent {
println("name is " + name)
}
The above class gives an error:
class Child needs to be abstract, since method name in trait Parent of type ⇒ String is not defined.
Of-course I can:
make the Child class abstract,
define it without using the private in the constructor like class Child(val name: String).
make the Parent an abstract class instead of a trait
But with the above implementation, is there no way I can have a private constructor parameter while extending a trait? Note that I want the variable to be private so that I should not be able to do childInstance.name.
Try this
trait Parent {
protected def name: String
require(name != "", "wooo problem!")
}
class Child(override protected val name: String) extends Parent {
val publicVar = "Hello World"
println("name is " + name)
}
def main(args: Array[String]): Unit = {
val child = new Child("John Doe")
println(child.publicVar)
println(child.name) // Does not compile
}
You will not be able to access to child.name
If you have an abstract method in a trait, then all the derived classes need to have the same (or more permissive) modifier (in your case at least protected) for the abstract methods.
trait Parent {
protected def name: String
require(name != "", "wooo problem!")
}
class Child(private val privateName: String) extends Parent {
override protected def name: String = privateName
println("name is " + name)
}
You can keep your constructor private, but you need to define the override protected def name: String and make use of the private value of your constructor.
I have several classes which extends a trait.
I created a factory method that uses pattern matching in order to instantiate the relevant class.
The problem is that whenever I create a new class that extend this trait I need to add it to the factory method manually.
is there an option to create the list of classes dynamically from all the classes available?
Thanks
some code examples:
current implementation :
object Test {
trait Parent
object Parent{
def apply(classType:String): Parent = classType match {
case "A" => new A
case "B" => new B
case "C" => new C
}
}
class A extends Parent
class B extends Parent
class C extends Parent
}
wanted behaviour:
object Test {
trait Parent
object Parent{
def apply(classType:String): Parent = SomeFunction(ClassType)
}
}
class A extends Parent
class B extends Parent
class C extends Parent
}
Using reflection get all the classes that extend this trait
get relevant classes and add them to list.
Alternatively you can create a Map which can help locate classes by some key
Code
package demo
trait Animal {
}
class Dog extends Animal
class Cat extends Animal
library used org.clapper" %% "classutil" % "1.0.11"
import org.clapper.classutil.{ClassFinder, ClassInfo}
object Main {
def main(args: Array[String]): Unit = {
val finder = ClassFinder()
val classes = ClassFinder.classInfoMap(finder.getClasses().iterator)
val impl = find("demo.Animal", classes)
impl.foreach(println)
}
def find(ancestor: String, classes: Map[String, ClassInfo]): List[ClassInfo] =
classes.get(ancestor).fold(List.empty[ClassInfo]) { ancestorInfo =>
val ancestorName = ancestorInfo.name
def compare(info: ClassInfo): Boolean =
info.name == ancestorName ||
(info.superClassName :: info.interfaces).exists {
n => classes.get(n).exists(compare)
}
val it = classes.valuesIterator
it.filter { info => info.isConcrete && compare(info) } .toList
}
}
output
demo.Dog
demo.Cat
note that most of the code is taken from this post and changed to suite current purpose Get all the classes that implments a trait in Scala using reflection
I am new to Lift and scala and trying to do some stuff.
in the moment i want to create polymorphic associations with the lift
mapper.
here one example:
i want to create a class Entry what can be an entry in any of the n
ListX objects. How can i accomplish to let parent and entries be
polymorphic?
Is there a generic Way to to these polymorphic associations with
OneToMany & ManyToMany in both directions?
class Entry extends BaseModel[Entry] {
def getSingleton = Entry
object parent extends MappedBase(this, AnyList)
}
object Entry extends Entry with LongKeyedMetaMapper[Entry] {
}
class ListA extends BaseModel[ListA] with OneToMany[Long, ListA] {
def getSingleton = ListA
object entries extends MappedOneToMany(Entry, Entry.parent)
}
object ListA extends ListA with LongKeyedMetaMapper[ListA] {
}
class ListB extends BaseModel[ListB] with OneToMany[Long, ListB] {
def getSingleton = ListB
object entries extends MappedOneToMany(Entry, Entry.parent)
}
object ListB extends ListB with LongKeyedMetaMapper[ListB] {
}
class ListC extends BaseModel[ListC] with OneToMany[Long, ListC] {
def getSingleton = ListC
object entries extends MappedOneToMany(Entry, Entry.parent)
}
object ListC extends ListC with LongKeyedMetaMapper[ListC] {
}