We started to use Dart's Strong mode with our polymer dart code and honestly it looks terrible. It looks so terrible that I need a second opinion on the matter. It cant be this ugly looking, it honestly cant.
So We were creating a bunch of PolymerDart views using some mix ins for generic code. This generic code is reused everywhere so hence why we made it a mixin.
Our old design:
abstract class MyModel{ ... }
class SubModel extends MyModel with JsProxy{ ... }
#behavior
abstract class MyBehavior implements PolymerBase {
#Property(notify:true)
MyModel model = null;
// ....
}
#PolymerRegister("my-component")
class MyViewModel extends PolymerElement with MyBehavior {
#Property(notify:true)
SubModel model = null;
// ...
}
The purpose was to have a generic model to represent information and we leverage it in the behavior. Since SubModel extends it, we can slot anywhere normally and the behavior would work. My colleague says this is a huge NO and I am confused as to why. He said it a Polymer Issue, so when we leave Polymer it will be able to be done sort of.
He then pushed through the code base a refactor so it works.
#PolymerRegister("my-component")
class MyViewModel extends PolymerElement with MyBehavior {
#Property(notify:true)
MyModel model = null; // <-- changed to parent type from Behavior
//example reference
void test(){
int id = (model as SubModel).id; // <-- using AS to explain what it really is.
}
}
Now he put this EVERYWHERE, updated all references of model.id with (model as SubModel).id. I think this is ugly and just plain wrong. (Granted I get that feeling with everything PolymerDart).
Is this really how this kind of thing is done when dealing with Mixins? Since The mixin already has that definition, we shouldn't need it in the MyViewModel code either.
Can someone explain this to me as to why this is the right thing according to strong mode? Why must this change occur? While I trust in my colleague, something does seem off and I would like a deeper understanding. I believe, that he is correct that maybe it is because entirely due to Polymer Dart, but maybe there is a way to circumventing all property renames, and using (.. as Whatever) everywhere.
analysis_options.yaml:
analyzer:
strong-mode: true
Edit: The reasoning was that since the Model is defined as a property in the behavior, it is non-mutable. We cant override the type in the MyViewModel class. Since SubModel extends MyModel, It should be allowed to exist.
Related
I have this:
public class Base {
public function whoAmI() {
trace("base");
}
}
public class Extended extends Base {
public function Extended() {
this.whoAmI() //prints extended
super.whoAmI() //prints base
var test = super;
test.whoAmI() //prints extended
}
public override function whoAmI() {
trace("extended");
}
}
The problem is when I do var test = super, it seems like this is assigned to test instead of super.
Is it possible to do the assignment so that test.whoAmI() prints "base"?
Edit: In the comments it is being said that using super in the way I propose would break overriding. I don't think that's the case. The way I am thinking of it, super could be used the same way as this. I understand that is not the way super is implemented, but using it that way would not break overriding as people are claiming. So for example the same way this is possible:
var test = this;
test.whoAmI();
This should be possible:
var test = super;
super.whoAmI();
It is obviously the choice of the language implementer to not do things this way, and I don't understand the reason why. It doesn't break things, but I guess it does make them more complicated.
I am not suggesting type-casting this to the super class. Obviously that wouldn't work.
You are thinking of "this" and "super" as 2 different instances, 2 different things but they in fact point to the same object (obviously) so at the end it's always "this". Using super is just a special keyword that allows the instance to point to the overrided definitions up the inheritance chain, it does not point to a different object. So "super" does correctly its job, it points to the instance and allow you each time you use it to access overrided definitions and that's it. There's of course no point on trying to store that keyword in a variable since in that case it just return correctly the instance it points to which is always "this".
It's simply a case of misunderstood inheritance principle and I've seen it before, super is mistaken for some kind of instance wrapper up the inheriatnce chain around the object "this" while it's in fact and always the same object.
No, this is not possible.
If this were possible, then overriding methods wouldn't be possible!
For example, take this function...
public function test(a:Object):void {
trace(a.toString());
}
You'd only get [object Object] back if your idea was how things worked.
Ok I understand what you mean your question is more about language definition and specification.
Look at this exemple in c# that explain how you can manage more precisely overriding in c# :
http://www.dotnet-tricks.com/Tutorial/csharp/U33Y020413-Understanding-virtual,-override-and-new-keyword-in-C
But
let's explain a litlle how it's work.
when you extend a class, it's like if you create an object composed of all the object in the inheritance tree so if B extends A and C extends B you have two objects like this:
(B+A) and (C+B+A) with hierarchy between each other B->A and C->B->A. Super is just a way to ascend in the hierachy.
When you cast a C in A for example. In memory you always have an object (C+B+A) but interpreted as A. When you override you just say that a method in child has an higher priority than in parent.
You can try downcasting this manually to any of your class's predecessors. The pointer will still be equal to this but the methods called will use the class table of the class used to downcast.
public class Extended extends Base {
public function Extended() {
this.whoAmI() //prints extended
super.whoAmI() //prints base
var test:Base = this;
test.whoAmI() //should print base
}
public override function whoAmI() {
trace("extended");
}
}
Should your Base extend something, which methods are known or the superclass is dynamic, and there is code that adds methods to prototype of a class, you might use such a downcast to call a superclass's method that might not be there at compile time, but make sure you first call hasOwnProperty in case of a dynamic class to determine whether a method or property exists.
Could someone please explain what does Refused Bequest means?
I tried reading some articles and says its a kind of code smell or in wiki it tells that it is a class that overrides a method of a base class in such a way that the contract of the base class is not honored by the derived class.
But in a nutshell or in a more simple terms, what is it actually?
I think you get it. Refused Bequest is a code smell. But, what type of code smell? Quoting Martin Fowler's book Refactoring: improving the design of existing code:
Subclasses get to inherit the methods and data of their parents. But
what if they don't want or need what they are given? They are given
all these great gifts and pick just a few to play with.
You have a subclass, that inherits from a parent class, but the subclass does not need all behaviour provided by the parent class. Because of that, the subclass refuses some behaviour (bequest) of the parent class. That's why this is a code smell.
Update answering #catzilla's comment:
If you don't have the opportunity to read the book (I totally recommend it), at least you have the SourceMaking page that describes it pretty well.
About a code example, let's try. Let's imagine we have some classes to compute a person's taxes. We could have a class that computes government taxes:
class Government {
protected double computeBaseTax() { //... }
protected double addPersonalTax(double tax) { //... }
public double getTax() {
double tax = computeBaseTax();
return addPersonalTax(tax);
}
}
Then, we could have a class that computes the amount of money a company has to pay as taxes. For whatever reason, we realized this class can reuse the addPersonalTax method, but not computeBaseTax(). And taking a bad decision, we decided that our Company class would inherit from Government.
class Company extends Government {
private double computeInitialTax() { //... }
#Override
public double getTax() {
double tax = computeInitialTax();
return addPersonalTax(tax);
}
}
Ok, the problem could be solved in a better way (overriding computeBaseTax() method) but I'm trying to ilustrate that Refused Bequest is a code smell that happens when we inherit from a base class and some functionality provided is refused.
Sorry this must be a very silly question.. but everywhere I've been seeing Scala code examples where you just do
contents+= on a BoxPanel or some layout Panel. I figured because they have contents as mutable.buffer so you can just add and remove components.
But how do you add a component to Scala Panel? It accepts a seq so do you have to give it a list or something? I know you can just call peer.add but I want to see how Scala code does it. :)
For example contents = new Button {} isn't working.
Sorry for this simple question I'm very new to Scala..
EDIT:
Thanks for the replies. My question now though becomes.. can you ever just have a class extending Panel? Would you be able to set contents for it at all? Or is it never done and everyone always just uses the Panels associated with a layout manager?
The Panel class itself is abstract, meaning it can't be instantiated directly, and is intended as a "base" for concrete implementations of panels.
It doesn't seem to have a "common" method for adding components probably because each subclass implements its own, sometimes mutually incompatible custom one:
BoxPanel, as you've noted, has a settable Buffer,
FlowPanel seems to mandate adding components as constructor arguments,
GridBagLayout and some others implement addition via the layout Map,
etc.
As you might see from the above examples, it would be hard to specify what a general "add" method would mean in all of those cases.
EDIT in response: of course you can, there's nothing stopping you from subclassing a Panel yourself and override the contents method, e.g.:
val myPanel = new Panel() {
private val myContents = (new Content += new Button())
override def contents = myContents
}
You can also use Panel as a type parameter for your methods that process panels in a general way, etc. It's just that you can't have an instance that's just a Panel, because, again, the class is abstract, so you can't instantiate it.
Note that this is not unique to Scala, if JPanel was abstract in Java (like Component is) the outcome would be the same.
I want to see how Scala code does it.
https://github.com/scala/scala-swing/blob/v1.0.0-RC2/src/main/scala/scala/swing/Container.scala#L35
I, too, practiced on some Swing code when I first learned some Scala.
Here is a Panel component that renders itself as a simple game grid:
https://github.com/som-snytt/House-of-Mirrors-Fork/blob/act/src/main/scala/hom/LightBox.scala#L286
To see how the Scala and Swing pieces fit together, see SuperMixin:
https://github.com/scala/scala-swing/blob/v1.0.0-RC2/src/main/scala/scala/swing/Component.scala#L51
Assembly:
https://github.com/som-snytt/House-of-Mirrors-Fork/blob/act/src/main/scala/hom/HouseOfMirrors.scala#L18
This is what you asked about directly:
https://github.com/som-snytt/House-of-Mirrors-Fork/blob/act/src/main/scala/hom/HouseOfMirrors.scala#L45
If you have a button:
val button=new Button{
text="Click me!"
}
or
val label=new Label{
text="Look, i'm a label!"
}
or
object myField extends TextField{ columns=2 }
then you just use:
contents=new BoxPanel(Orientation.Vertical){
contents+=button
border=Swing.EmptyBorder(10,20,10,20)
}
or in a more simpler form:
contents=new FlowPanel(){
contents+=new Label("This is my button:")
contents+=new Button("Click me!")
border=Swing.EmptyBorder(10,20,10,20)
}
I'm currently working on a project where I have a ton of classes inheriting from other classes which inherit from other classes and so on. It's probably more complex than it should be, but I am a sucker for abstraction.
Anyway, at times I need to change a getter/setter from being public to private. I suppose it's not really a need, but a desire to cut off things that are preset in child classes, but still need to be publicly accessible in the parent classes.
So an example would be:
Class Base {
public function set label( value:String ):void{};
}
Class A extends Base {}
Class B extends A {
public function B() {
super();
this.label = "stuff";
}
override public function set label( value:String ):void {
//this setter should not be publicly available since the label should not be possible to change in this class
}
}
Currently, I am doing one of two things in these cases:
override the setter to do nothing or set it to the default value so that it can still update/render/whatever
throw an error saying it is unavailable in that class
I've done some searching and everything seems to point to this being impossible, but I've never found it explicitly stated that it is impossible. So is it possible to change the access modifier on an inherited property/function?
It is not possible, and it really should not be, because it leads to confusing and unpredictable class hierarchies. For starters, if you did something like that, you would break the Liskov Substitution Principle: A super class should at all times be replaceable by its derived classes. Changing the API would clearly prevent that - and thus possibly lead to runtime errors and/or inexplicable glitches, if another programmer accidentally exchanged types.
If the classes you are modeling have different behavior in such a way that would make you "hide" an otherwise public API method, you should probably not use inheritance for this - or perhaps in a different way. From what you are describing, I would guess that in a larger part of your hierarchy, you should probably be using composition instead of inheritance, anyway.
It is not possible for the very reason in the comments by Marty Wallace. But it's not an uncommon thing to do.
However in the alternative you used, The property owner is the base class & hence it should always know of anything that the derived class does with it's own properties.
Instead of your hack I would thus prefer something like this :
public class Base {
protected var _isLabelUsable:Boolean = true;
public function set label( value:String ):void {
if (!_isLabelUsable)
throw new Error("Access of undefined property label.");
// Set Label here
}
}
public class A extends Base {
}
public class B extends A {
public function B() {
super();
_isLabelUsable = false;
}
}
These are all valid points, but...
There are cases where they are all void.
Given a base class that comes from an external source. Like, say, mx:Panel.
It has the property 'titleIcon:Class'
The derived class inherits all properties and functions. But people using it shall never set the titleIcon directly, because part of the derived class' functionality depends on the availability of an icon name being known. It provides a property iconName:String. Setting it will also set the titleIcon.
Now how to prevent people from still setting the icon directly? The UI is offering the old property for AS3 and MXML, and the compiler will (of course) not complain.
If titleIcon is a setter/getter pair (in this case, it is), and not final, then the derived class can override the setter and throw an error, while the iconName setter will assign the icon class to super.titleIcon.
However, this is clumsy and will not work for final functions or variables.
If there were a way to at least tell the UI to not offer the property anymore or show a warning...
The problem I'm having is while using Linq2Sql with inheritance after declaring a new instance of the inherited class the discriminator property is still set to its initial value, not the correct value for the sub-type. It gets the correct value after attaching it to a context and calling SubmitChanges(). There are times where I want to declare a new object of the inherited type and call methods on the base class with the base class knowing inherited type it is working with and the most logical choice would be to use the discriminator property.
Is there a way to force the setting of the discriminator property? I don't want to go to all my sub-classes and implement the OnCreated() partial method for something the context already knows how to do.
I did come up with a slightly better workaround than putting code in the OnCreated() method of each inheriting class and figured I'd leave it here in case anyone stumbles here.
In the OnCreated() of the base class I added code that looked similar to this:
partial void OnCreated()
{
if (this is BaseClass1)
{
this.[DiscriminatorProperty] = DiscriminatorValueForBaseClass1;
}
else if(this is BaseClass2)
{
this.[DiscriminatorProperty] = DiscriminatorValueForBaseClass2;
}
}
It is still duplicating the functionality that the context already knows how to do but at least I'm not implementing the OnCreated() in every base class. I also don't like the fact that if a new class is added or a discriminator value changes you have to update it in the DBML and in the OnCreated(). For this reason I'd still like a way for the context to assign the value, in fact it should be doing this when the inherited class is created.