Kotlin- Generic functions - swing

I am currently trying to write a dsl that allows building Swing user interfaces easily. In order to achieve that and not having to support all types of components i wanted to make a generic function to add a container, which in my case means everything that extends JPanel.
What i ended up with was this:
fun <T : JPanel> container(containerComponent: T = JPanel(), constraints: LC = LC(), setup: T.() -> Unit): T {
containerComponent.setup()
containerComponent.layout = MigLayout(constraints)
return containerComponent
}
However, on line one, at the first parameter, i get an error Type mismatch: Required T, but found JPanel, but i don't really understand why, since i specified that T will be something that extends JPanel.

As #shmosel pointed out already, T might still be something other than JPanel which will lead to JPanel not satisfying T.
Here is an example of what one might do:
val setup: JPanelExtendingClass.() -> Unit = {
//Perform actions on splitpane
}
container(constraints = LC(), setup = setup)
This would lead to T being JPanelExtendingClass which JPanel doesn't conform to.
Therefore i ended up splitting the whole thing into two methods, one specifically for JPanel
fun panel(constraints: LC = LC(), setup: JPanel.() -> Unit): JPanel {
return container(JPanel(), constraints, setup)
}
and another one for anything extending JPanel
fun <T : JPanel> container(containerComponent: T, constraints: LC = LC(), setup: T.() -> Unit): T {
containerComponent.setup()
containerComponent.layout = MigLayout(constraints)
return containerComponent
}
this one does not define any default component though.

You want to have a function that can have any JPanel type as a parameter, and if one doesn't specify the parameter value, it will be JPanel.
Now suppose, you are calling the function in this way:
container<JPanelExtendingClass> { ... }
In this case, the type of the containerComponent parameter will be JPanelExtendingClass, and the value will be JPanel().
JPanel is not a subclass of JPanelExtendingClass, so the compiler rejects it.
Here you don’t actually need that function to be generic, you can change the function to
fun container(containerComponent: JPanel = JPanel(), constraints: LC = LC(), setup: JPanel.() -> Unit): JPanel {...}

Related

Passing two different types of data in a vector using interface

In Actionscript3, as the title says, I'm trying to pass two different types of data in one vector through creating an interface for it. Does anybody have an example to do so?
If they are unrelated objects, you might consider an Array instead. If you want the features of a Vector, then you just treat it like usual: create a Vector with the interface as the type instead of the most common base class.
var v:Vector.<IFace> = new Vector.<IFace>();
...and of course implement IFace on those classes you want to put into the Vector
UPDATE - OK, as an extension of the answer, here's an actual interface...
public interface IFace
{
function doSomethingAllImplementersCanDo() : Boolean;
}
...that would go in a file called IFace.as. A class that implements IFace might look like this...
public class MonsterTruck implements IFace
{
public function doSomethingAllImplementersCanDo() : Boolean
{
return true;
}
}
...and somewhere else in your program...
var v:Vector.<IFace> = new Vector.<IFace>();
var mt:MonsterTruck = new MonsterTruck();
v.push( mt );
var throughIFace:IFace = v.pop();
trace( throughIFace.doSomethingAllImplementersCanDo() );
I recommend checking out Adobe documentation here: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f41.html

AS3 How to declare an object without the dreaded "Conflict Exists" error?

I am designing a simple game in Flash and have come across this error. I have no idea how to go about this in actionscript and would appreciate any help.
Basically, I have a switch statement which creates an object of different type depending on each case (as I would prefer not to duplicate the same ten lines of code for each case) and I am getting a "conflict exists with definition in namespace internal" compiler error and I think I understand why.
switch(power){
case 1:
var Pow:objectOne = new objectOne();
break;
case 2:
var Pow:objectTwo = new objectTwo();
break;
}
My question however is this - what is the proper way of going about this?
I initially thought of declaring the variable before the switch statement which results in an "implicit coercion of a value of type object(One/Two) to an unrelated type Class" error. What am I missing here?
Aside from the compiler error you are experiencing, another problem here is that you are planning on using the pow variable later in your code, yet they are of different types. My suggestion is to use the benefits of Inheritance in OOP and create a base class that your two custom classes can inherit from. That way they are both technically of the same base type, while still giving you the freedom to customize each custom class, while keeping similar functionality in the base class.
Remember, OOP is here to always help you and is there to avoid issues like the one you have come across, but here is how I would do it, and I tested the following implementation in Flash CC 2014 and it compiled successfully:
Example .FLA:
var pow:BaseClass;
var power = 1;
switch(power){
case 1:
pow = new ObjectOne();
break;
case 2:
pow = new ObjectTwo();
break;
}
pow.whichObjectAmI(); // this will simply trace what object pow is
Base Class
package {
public class BaseClass {
public function BaseClass() {
// constructor code
}
public function whichObjectAmI() {
trace("I am the base class");
}
}
}
Object One
package {
public class ObjectOne extends BaseClass {
public function ObjectOne() {
// constructor code
}
override public function whichObjectAmI() {
trace("I am Object One!");
}
}
}
Object Two
package {
public class ObjectTwo extends BaseClass {
public function ObjectTwo() {
// constructor code
}
override public function whichObjectAmI() {
trace("I am Object Two!");
}
}
}
You can always inherit from any of ActionScript's classes as well like MovieClip, Button, etc. And by doing so, you're adding custom functionality on top of their functionality so 1) you don't have to rebuild a bunch of functionality, and 2) giving you the chance to reuse their functionality while adding your own custom code!
Disclaimer: My AS3 is a little rusty ;)
Of what type would the variable Pow be after the switch statement? objectOne or objectTwo? From the compiler's perspective objectOne and objectTwo could be totally different from each other (read: methods, fields,...)
So:
A) Keep variable name for both assignments but declare it before the switch-statement AND use a common base-type (object, MovieClip,...)
B) Have 2 different variables: var PowOne: objectOne and var PowTwo: objectTwo
I think option A would be preferable...

How can I create a subclass that takes in different parameters for the same function name?

So I have made this simple interface:
package{
public interface GraphADT{
function addNode(newNode:Node):Boolean;
}
}
I have also created a simple class Graph:
package{
public class Graph implements GraphADT{
protected var nodes:LinkedList;
public function Graph(){
nodes = new LinkedList();
}
public function addNode (newNode:Node):Boolean{
return nodes.add(newNode);
}
}
last but not least I have created another simple class AdjacancyListGraph:
package{
public class AdjacancyListGraph extends Graph{
public function AdjacancyListGraph(){
super();
}
override public function addNode(newNode:AwareNode):Boolean{
return nodes.add(newNode);
}
}
Having this setup here is giving me errors, namely:
1144: Interface method addNode in namespace GraphADT is implemented with an incompatible signature in class AdjacancyListGraph.
Upon closer inspection it was apparent that AS3 doesn't like the different parameter types from the different Graph classes newNode:Node from Graph , and newNode:AwareNode from AdjacancyListGraph
However I don't understand why that would be a problem since AwareNode is a subClass of Node.
Is there any way I can make my code work, while keeping the integrity of the code?
Simple answer:
If you don't really, really need your 'addNode()' function to accept only an AwareNode, you can just change the parameter type to Node. Since AwareNode extends Node, you can pass in an AwareNode without problems. You could check for type correctness within the function body :
subclass... {
override public function addNode (node:Node ) : Boolean {
if (node is AwareNode) return nodes.add(node);
return false;
}
}
Longer answer:
I agree with #32bitkid that your are getting an error, because the parameter type defined for addNode() in your interface differs from the type in your subclass.
However, the main problem at hand is that ActionScript generally does not allow function overloading (having more than one method of the same name, but with different parameters or return values), because each function is treated like a generic class member - the same way a variable is. You might call a function like this:
myClass.addNode (node);
but you might also call it like this:
myClass["addNode"](node);
Each member is stored by name - and you can always use that name to access it. Unfortunately, this means that you are only allowed to use each function name once within a class, regardless of how many parameters of which type it takes - nothing comes without a price: You gain flexibility in one regard, you lose some comfort in another.
Hence, you are only allowed to override methods with the exact same signature - it's a way to make you stick to what you decided upon when you wrote the base class. While you could obviously argue that this is a bad idea, and that it makes more sense to use overloading or allow different signatures in subclasses, there are some advantages to the way that AS handles functions, which will eventually help you solve your problem: You can use a type-checking function, or even pass one on as a parameter!
Consider this:
class... {
protected function check (node:Node) : Boolean {
return node is Node;
}
public function addNode (node:Node) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
In this example, you could override check (node:Node):
subclass... {
override protected function check (node:Node) : Boolean {
return node is AwareNode;
}
}
and achieve the exact same effect you desired, without breaking the interface contract - except, in your example, the compiler would throw an error if you passed in the wrong type, while in this one, the mistake would only be visible at runtime (a false return value).
You can also make this even more dynamic:
class... {
public function addNode (node:Node, check : Function ) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
Note that this addNode function accepts a Function as a parameter, and that we call that function instead of a class method:
var f:Function = function (node:Node) : Boolean {
return node is AwareNode;
}
addNode (node, f);
This would allow you to become very flexible with your implementation - you can even do plausibility checks in the anonymous function, such as verifying the node's content. And you wouldn't even have to extend your class, unless you were going to add other functionality than just type correctness.
Having an interface will also allow you to create implementations that don't inherit from the original base class - you can write a whole different class hierarchy, it only has to implement the interface, and all your previous code will remain valid.
I guess the question is really this: What are you trying to accomplish?
As to why you are getting an error, consider this:
public class AnotherNode extends Node { }
and then:
var alGraph:AdjacancyListGraph = new AdjacancyListGraph();
alGraph.addNode(new AnotherNode());
// Wont work. AnotherNode isn't compatable with the signature
// for addNode(node:AwareNode)
// but what about the contract?
var igraphADT:GraphADT = GraphADT(alGraph);
igraphADT.addNode(new AnotherNode()); // WTF?
According to the interface this should be fine. But your implemenation says otherwise, your implemenation says that it will only accept a AwareNode. There is an obvious mismatch. If you are going to have an interface, a contract that your object should follow, then you might as well follow it. Otherwise, whats the point of the interface in the first place.
I submit that architecture messed up somewhere if you are trying to do this. Even if the language were to support it, I would say that its a "Bad Idea™"
There's an easier way, then suggested above, but less safe:
public class Parent {
public function get foo():Function { return this._foo; }
protected var _foo:Function = function(node:Node):void { ... }}
public class Child extends Parent {
public function Child() {
super();
this._foo = function(node:AnotherNode):void { ... }}}
Of course _foo needs not be declared in place, the syntax used is for shortness and demonstration purposes only.
You will loose the ability of the compiler to check types, but the runtime type matching will still apply.
Yet another way to go about it - don't declare methods in the classes they specialize on, rather make them static, then you will not inherit them automatically:
public class Parent {
public static function foo(parent:Parent, node:Node):Function { ... }}
public class Child extends Parent {
public static function foo(parent:Child, node:Node):Function { ... }}
Note that in second case protected fields are accessible inside the static method, so you can achieve certain encapsulation. Besides, if you have a lot of Parent or Child instances, you will save on individual instance memory footprint (as static methods therefore static there exists only one copy of them, but instance methods would be copied for each instance). The disadvantage is that you won't be able to use interfaces (can be actually an improvement... depends on your personal preferences).

Castle Windsor resolve named instance and unnamed instance incorrect

I have following testing code trying to get one instance for generic and other for special purpose.
[TestMethod]
public void Test_Name_And_Named_Instances()
{
//MyClass implemented IMyClass
MyClass genericInstance = new MyClass("generic");
MyClass specialInstance = new MyClass("special");
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For(IMyClass).Instance(genericInstance));
container.Register(Component.For(IMyClass).Instance(specialInstance).Named("special"));
IMyClass genericOne = container.Resolve<IMyClass>();
IMyClass specialOne = container.Resolve<IMyClass>("special");
Assert.AreSame(genericOne, genericInstance); //true
Assert.AreNotSame(genericOne, specialOne); //false
}
I expect to get two different instances, but the result is both genericOne and specialOne points to same objec genericInstance.
Any idea?
This doesn't compile:
container.Register(Component.For(IMyClass).Instance(genericInstance));
Should be:
container.Register(Component.For<IMyClass>().Instance(genericInstance));
Other than that, the test passes for me (Windsor 2.5.2)
EDIT:
If you flip the registrations, the test fails. This is by design. When you resolve without an explicit name, you're saying "give me the default component for this service", which in Windsor is the first registered component for that service type, by default.
If you need different components under the same service type, assign explicit names to all of them when registering and resolving.

Castle Windsor: Re-registration of a Named component maintains previous Lifestyle

The below Unit Test fails, and I am looking for a valid reason for it doing so.
interface IFoo { }
class Foo : IFoo { }
class Foo2 : IFoo { }
[TestMethod]
public void LifestyleTest4()
{
WindsorContainer container = new WindsorContainer();
container.Register(Component.For<IFoo>().ImplementedBy<Foo>().Named("foo").LifeStyle.Singleton);
IHandler h = container.Kernel.GetHandler("foo");
Assert.IsTrue(h.ComponentModel.LifestyleType == LifestyleType.Singleton);
bool removed = container.Kernel.RemoveComponent("foo");
Assert.IsTrue(removed);
container.Register(Component.For<IFoo>().ImplementedBy<Foo2>().Named("foo").LifeStyle.Transient);
h = container.Kernel.GetHandler("foo");
//Assert will fail as LifestyleType == Singleton
Assert.IsTrue(h.ComponentModel.LifestyleType == LifestyleType.Transient, "Expected Transient Lifestyle");
}
Even though the component was removed from the container, it appears that a reference to the LifeStyle is maintained by name.
I am using the 2.0 release.
Krzysztof is right, this looks like a bug.
The reason is that the component configuration, which contains the lifestyle, is not removed by RemoveComponent, so the first lifestyle configuration will be always used.
Workaround: add this line after calling RemoveComponent():
container.Kernel.ConfigurationStore.GetComponentConfiguration("foo").Attributes.Remove("lifestyle");
Please report it to the issue tracker (include your testcase) and link back here, this could serve as a starting point to fix the bug.