Cannot create custom Appender for log4j2 in scala - scala

I try to create a custom Appender in Scala (to use it in UTs), to migrate log4j1 to log4j2, but i cannot.
in log4j1 it's like:
class TestAppender extends AppenderSkeleton {
}
now i'm doing somting like:
class TestAppender extends AbstractAppender {
}
but i get
Cannot resolve overloaded constructor `AbstractAppender`
Any thoughts on how to do so?

In Java, you call the superclass constructor in your constructor with super(arguments). In Scala, however, because the body of the class (excluding defs) is the default constructor for the class, the superclass constructor is called by passing the arguments in the extends clause:
class TestAppender extends AbstractAppender(...) {
Since the only non-deprecated constructor for AbstractAppender appears to be this one, you almost certainly want something like:
class TestAppender extends AbstractAppender("test", someFilter, someLayout, whetherToIgnoreExceptions, Array()) {
If you want to allow the user of your class to specify a parameter for AbstractAppender, then you would do something like:
class TestAppender(ignoreExceptions: Boolean) extends AbstractAppender("test", someFilter, someLayout, ignoreExceptions, Array()) {

Related

Make constructor parameters public in subclass

I want the protected fields of a class to be made publicly visible in a subclass:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao])
Now I want to access someDao like so:
val testClass = new TestMyClass
testClass.someDao
I've read that in Java and Scala access modifiers can be broadened but not restricted in subclasses (although these are just constructor parameters, not private fields per se). How can I achieve that in this example?
EDIT:
The answers provided suggest making someDao public in the base class. This is not what I want. I want it to remain private, but just change its visibility to public in the TestMyClass class.
As far as I know, an overriden val cannot access the super implementation.
If you can modify the base class, one solution is to explicitely define an accessor method, which can be overriden; something like this:
class MyClass(_someDao: SomeDao) {
protected def someDao = _someDao
}
class TestMyClass extends MyClass(mock[SomeDao]) {
override def someDao = super.someDao
}
If you cannot change the base class, one workaround would be to define a public accessor method with a different name:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao]) {
def someDao2 = someDao
}
Add var or val to parameters declaration:
class MyClass(val someDao: SomeDao)
In this case only getter function will be generate for someDao field. So when you write testClass.someDao you retrieve not the someDao as field you use their getter function.
Good example about visibility of class parameters in Scala demostrated at this article.
Regarding to your last updates
Set package scope for parameter declaration:
class MyClass(private[lastPackageOfSomeDao] val someDao: SomeDao)

Calling a member method without the 'this' keyword

In Scala, is it possible to call a member method without having to call an instance of itself?
For instance, having this class:
class Model {
def action(value : String) = {
// Do action
}
}
this object implementation works:
object MyModel extends Model {
this action "doSomething"
}
But I would like to do something like this:
object MyModel extends Model {
action "doSomething"
}
As one does with Java property files, since it's a neat way to define the state of an object.
I managed to define an alias for this:
def declare = this
but it's the same issue of having to use a word in front of the call to the member method.
Is there an option to do this?
Yes, but you have to use parentheses:
object MyModel extends Model {
action("doSomething")
}
See this answer for example for more detail about when parentheses can or cannot be omitted.
As a side note, you could also alias this as follows:
object MyModel extends Model { declare =>
declare action "doSomething"
}
This is often useful if you want to refer to a class's this from inside of a nested class—it's a bit less verbose than writing Outer.this.x as you would in Java.

base class constructor parameter in trait

I have a base class with some constructor parameter:
abstract class HugeClass(implicit context: ContextClass) {
...
}
Because the class gets bigger and bigger and only some subclasses need some special behaviour, I want to refactor it into a trait. However, I still need access to context in the trait. I tried this:
trait SomeTrait extends HugeClass {
def myMethod = {
context.method
}
}
But the scala compiler says: not found: value context. How can I solve that?
Parameter context is turned into a private field. The fact that a parameter or a member is implicit does not mean it is public - it is implicit only within the class it is visible in (HugeClass).
Turn context into a val:
abstract class HugeClass(implicit val context: ContextClass) {
...
}
and it will work.

How to define a parameterless constructor in Scala

This question is so stupid... Anyway, i just can't find the right information, because every Scala-constructor example class i see works with at least one parameter.
I want to have this class translated from Java to Scala:
public class SubscriptionConverter extends Converter {
public SubscriptionConverter() {
Context ctx = new InitialContext();
UserEJB userEJB = (UserEJB) ctx.lookup("java:global/teachernews/UserEJB");
}
(...)
}
So i only have a parameterless constructor. I messed around in Scala with this(), but i couldn't get a similar example like the one above working.
How do i do i write that in Scala?
Any statements declared at the class level are executed as part of the default constructor. So you just need to do something like this:
class SubscriptionConverter extends Converter {
val ctx = new InitialContext
val userEJB = ctx.lookup("java:global/teachernews/UserEJB")
(...)
}
#dbyrne has covered the most important parts, but I'll add a few side details.
If a class has no parameters, and it's immutable, consider declare it as an object instead.
The constructor defined by statements at the class level and by parameter lists after the class name is known as the primary constructor. * Auxiliary constructors* are defined by def this() = .... Unlike Java, each auxiliary constructor must delegate to the primary constructor.
When you declare a primary constructor with zero parameter lists, the compiler will automatically add a single, empty parameter list. If you define a constructor with one implicit parameter list, the compiler will add an empty parameter list before this.

Private and protected constructor in Scala

I've been curious about the impact of not having an explicit primary constructor in Scala, just the contents of the class body.
In particular, I suspect that the private or protected constructor pattern, that is, controlling construction through the companion object or another class or object's methods might not have an obvious implementation.
Am I wrong? If so, how is it done?
You can declare the default constructor as private/protected by inserting the appropriate keyword between the class name and the parameter list, like this:
class Foo private () {
/* class body goes here... */
}
Aleksander's answer is correct, but Programming in Scala offers an additional alternative:
sealed trait Foo {
// interface
}
object Foo {
def apply(...): Foo = // public constructor
private class FooImpl(...) extends Foo { ... } // real class
}