Kotlin - How to make field read-only for external classes - field

I have the following Kotlin class on Android:
class ThisApplication: Application() {
lateinit var network: INetwork
override fun onCreate() {
super.onCreate()
network = Network()
}
}
Now, any external class can get the INetwork reference by simply doing:
application.network
However, that also makes it possible for an external class to overwrite that value:
application.network = myNewNetworkReference
I want to avoid the second option. Unfortunately, I can't make the field val because its initialization needs to happen inside the onCreate callback.
I also thought about making the field private and exposing it through a function, like this:
private lateinit var network: INetwork
fun getNetwork() = network
However, whoever calls getNetwork() can still assign a new value to it, like so:
application.getNetwork() = myNewNetworkReference
How can I make the network field to be read-only by external classes? Or even better, is there a way to make it val even though I can't initialize it inside a constructor?

To restrict the access from the external classes, you can change the visibility of accessors. For your case, you need private setter and public getter with lateinit modifier:
lateinit var network: INetwork
private set
Or a read-only lazy property:
val network: INetwork by lazy { Network() } //you can access private property here, eg. applicationContext
There are some misunderstanding from you about this code:
private lateinit var network: INetwork
fun getNetwork() = network
Kotlin is pass-by-value as what Java does. So, application.getNetwork() = myNewNetworkReference is not a valid statement. We cannot assign value to the return value of a function.

You can modify the visibility of the getters/setters independantly from the actual variable:
lateinit var network: INetwork
private set

Would val network: INetwork by lazy { ... } work for your scenario?
The lambda expression gets called with the first reference to the field network. Obviously, this isn't the same as deferring initialization to the OnCreate method, but it is a way to make it val without having to initialize it in the constructor.
There are other delegation choices as well. The Kotlin documentation is worth checking out.

Related

Dart: should the instance variables be private or public in a private class?

For example:
class _Foo {
String _var1;
String var2;
}
I always use public variable var2 because I think it's no point to make private variables when the class is already private, because you can not access private class anyway.
But I found many people use private variable _var1. Is this just a personal preference? When the class is private, what is the point of private instance variable? If you can not access the private class, you can not access all of its instance variables regardless whether they are private or not. If you can access the private class in the same lib, then you can access its all instance variables regardless whether they are private or not.
Making the class private doesn't make its members private and it doesn't make instances of that class inaccessible.
Assume
lib/private_class.dart
class Foo {
final _PrivateClass privateClass = _PrivateClass();
}
class _PrivateClass {
String publicFoo = 'foo';
String _privateBar = 'bar';
}
bin/main.dart
import 'package:so_53495089_private_field_in_private_class/private_class.dart';
main(List<String> arguments) {
final foo = Foo();
print(foo.privateClass.publicFoo);
// print(foo.privateClass._privateBar); // invalid because of ._privateBar
}
You can't declare variables or parameters of the type of a private class or extend or implement the class in another library or create an instance of that class,
but otherwise there is not much difference.
So if the field is supposed to be hidden (internal state) to users of the API, then make the field private.

Jenkins Shared Library Immutable Singleton

I have a Singleton patter class in my Jenkins shared library:
public class Configuration {
private static final INSTANCE = new Configuration()
static getInstance() { return INSTANCE }
private Configuration() {
}
def initialize(env, params) {
Foo = params.FOO;
}
public String Foo = ''
}
Later I can call this from elsewhere using something like this:
Configuration.instance.initialize(env, params);
config = Configuration.instance;
println 'FOO: ' + config.Foo
Ideally, I want the benefit of the Singleton pattern, but I don't want some fields to be overridden by consumers.
First Attempt:
On first thought, I would think this would work:
public class Configuration {
private static final INSTANCE = new Configuration()
static getInstance() { return INSTANCE }
private Configuration() {
}
def initialize(env, params) {
INSTANCE.#Foo = params.FOO;
}
public final String Foo = ''
}
Error:
groovy.lang.GroovyRuntimeException: Cannot set the property 'Foo' because the backing field is final.
Second Attempt:
On Second thought, I would think initializing in the constructor would work, however I don't seem to have access to params and env, unless these are passed in from the vars function, via the initialize() method.
How can I make this Singleton class immutable, or its fields read only?
I think you Could:
Define your class with "implements Serializable", as documentation advices.
Implement the constructor that would accept 1 parameter of type BaseScript, and pass this to it upon instantiation, relative to that this (which you could call internal script) you can refer to script.params, script.env, etc. and I mean you don't HAVE to use initialize, you can do all you want in the c'tor.
But wait, please tell more:
why does CI/CD code need to have a Singleton?
You're passing its data as parameters [so it's not really an immutable entity :)]
Maybe you could "simply" create an immutable map out of your parameters....
Configuration as singleton feels as if you can delegate configuration management to ... configuration management service (consul, etcd, or others).
Please elaborate, it's very curious!
Also you referred to something as "consumers". are these library consumers? or people running the jobs?
Thank you!

Bind list of objects using Guice + Kotlin

I'm writing a JavaFX application in Kotlin with the following controller definition:
class MainController {
#Inject private lateinit var componentDescriptors: List<ComponentDescriptor>
/* More code goes here */
}
I'm using Guice for Dependency management. And I'm trying to inject the list of class instances loaded via java.util.ServiceLoader. My problem is to define a binding that will inject the list of loaded object instances into the declared field. I tried annotation based provisioning:
internal class MyModule: AbstractModule() {
override fun configure() { }
#Provides #Singleton
fun bindComponentDescriptors(): List<ComponentDescriptor> =
ServiceLoader.load(ComponentDescriptor::class.java).toList()
}
and multibinding extension (switched List to Set in field definition of corse):
internal class MyModule: AbstractModule() {
override fun configure() {
val componentDescriptorBinder = Multibinder.newSetBinder(binder(), ComponentDescriptor::class.java)
ServiceLoader.load(ComponentDescriptor::class.java).forEach {
componentDescriptorBinder.addBinding().toInstance(it)
}
}
}
but both of these approaches leads to the same error:
No implementation for java.util.List<? extends simpleApp.ComponentDescriptor> was bound.
while locating java.util.List<? extends simpleApp.ComponentDescriptor>
for field at simpleApp.MainController.componentDescryptors(MainController.kt:6)
while locating simpleApp.MainController
1 error
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
at com.gluonhq.ignite.guice.GuiceContext.getInstance(GuiceContext.java:46)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:929)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
... 12 more
I'm starting to suspect that it somehow related to Kotlin gerenic variance and Guice strict type checking. But I don't know how to declare the binding so Guice will know what to inject into this field.
Yes, it happens because of variance but there's a way to make it work.
class MainController {
#JvmSuppressWildcards
#Inject
private lateinit var componentDescriptors: List<ComponentDescriptor>
}
By default Kotlin generates List<? extends ComponentDescriptor> signature for the componentDescriptors field. The #JvmSuppressWildcards makes it generate a simple parameterized signature List<ComponentDescriptor>.
#Michael gives the correct answer and explanation. Here's an example of one strategy for unit testing a Set multibinding for those that like to test their modules:
class MyModuleTest {
#JvmSuppressWildcards
#Inject
private lateinit var myTypes: Set<MyType>
#Before fun before() {
val injector = Guice.createInjector(MyModule())
injector.injectMembers(this)
}
#Test fun multibindings() {
assertNotNull(myTypes)
assertTrue(myTypes.iterator().next() is MyType)
}
}
#Michael comment is working. If you want to do the injection in constructor, you need do something like
class MainController #Inject consturctor(
private var componentDescriptors: List<#JvmSuppressWildcards ComponentDescriptor>
) {}

Why can I use reflection to call private methods of an external class?

I can use reflection to access and call private methods of a class outside of my library. Is this a bug or desired behaviour? If it's desired, how can I make it impossible for external code to access private members/methods?
library left;
class Thing {
void _priv(String s) {
print(s);
}
}
library right;
void main() {
var t = new Thing();
var mirror = reflect(t);
mirror.type.declarations.values
.where( (d) => d.isPrivate && d is MethodMirror )
.forEach( (d) {
print(d.simpleName == #_priv); // prints false
mirror.getField(d.simpleName).reflectee("Hello World"); // prints Hello World
});
}
This privacy is not a security feature, is's only to communicate to users of your API that such a method is intended for internal usage only. Access using mirrors can't be prevented.
Disallowing it in mirrors wouldn't prevent access because the VM and dart2js just mangle or prefix private method names to prevent name collisions with public methods. These names can be predicted or found using brute force and then be called.
Calling private methods are mostly useful in writing the DSL(Domain Specific Language)s.

Autofac get decorated QueryHandler by convention based on constructor parameter name?

We inject IQueryHandler<TQUery,TResult> into our MVC controllers. We globally register all of these in the container
We have written a decorator that can cache the results of IQueryHandler.
We want to sometimes get cached reults and other times not from the same handler.
Is it possible to conditionally get a decorated handler based on the name of the constructor parameter. e.g. inject IQueryHandler<UnemployedQuery, IEnumerable<People>> cachedPeopleHandler if we prefix constructor parameter name with cached we actually get it wrapped with decorator?
Just trying to use a more convention over configuration approach to simplify things.
Yes it's possible to do it. Below is a simple working example on how you can achieve it:
class Program
{
public interface IQueryHandler{}
private class QueryHandler : IQueryHandler
{
}
private class CacheQueryHandler : IQueryHandler
{
}
public interface IService
{
}
private class Service : IService
{
private readonly IQueryHandler _queryHandler;
private readonly IQueryHandler _cacheQueryHandler;
public Service(IQueryHandler queryHandler, IQueryHandler cacheQueryHandler)
{
_queryHandler = queryHandler;
_cacheQueryHandler = cacheQueryHandler;
}
public override string ToString()
{
return string.Format("_queryHandler is {0}; _cacheQueryHandler is {1}", _queryHandler,
_cacheQueryHandler);
}
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
// Register the dependency
builder.RegisterType<QueryHandler>().As<IQueryHandler>();
// Register the decorator of the dependency
builder.RegisterType<CacheQueryHandler>().Keyed<IQueryHandler>("cache");
// Register the service implementation
builder.RegisterType<Service>().AsSelf();
// Register the interface of the service
builder.Register(c =>
{
var ctor = typeof (Service).GetConstructors()[0];
var parameters =
ctor.GetParameters()
.Where(p => p.Name.StartsWith("cache"))
.Select(p => new NamedParameter(p.Name, c.ResolveKeyed("cache", p.ParameterType)));
return c.Resolve<Service>(parameters);
}).As<IService>();
using (var container = builder.Build())
{
var service = container.Resolve<IService>();
Console.WriteLine(service.ToString());
Console.ReadKey();
}
}
}
Update:
Basically you need to:
1. Think up a general convention. Prefix "cache" of ctor parameter name in your case.
2. Register your dependencies as usual.
3. Register your decorators, so they don't overwrite your original dependencies and you can easily resolve them basing on your convention. e.g. Keyed, Named, via Attribute, etc.
4. Register you actual implementation of class that uses decorators
5. Register your interface that describes the class via lambda expression that has all magic inside.
Note: I provided just a simple and working example. It's on you to make it nice, easy to use and fast e.g. make it as an extension, generic, cache reflection results etc. It's not difficult anyway.
Thanks.

Resources