Closure Compiler warns "Bad type annotation. Unknown type …" when Ecmascript 6 class is extended - class

I'm getting a warning for every Ecmascript 6 class that inherits from another class when compiling with Closure Compiler:
I've dumbed things down as much as possible and still get the warning:
/src/main/js/com/tm/dev/Dog.js: WARNING - Bad type annotation. Unknown type module$$src$main$js$com$tm$dev$Animal.default
The compiled code does run correctly. (I've tried a number of annotations which only made things worse.) Anyone know what's expected here?
Animal.js:
export default class{
constructor(){
this.legs = [];
}
addLeg(legId){
this.legs.push( legId );
}
}
Dog.js:
import Animal from './Animal';
export default class extends Animal {
constructor(){
super();
[1,2,3,4].forEach(leg=>this.addLeg(leg));
console.log( 'Legs: ' + this.legs.toString() );
}
}

A hint is in the warning message, though it would obviously be confusing if you're not familiar with Closure Compiler's annotation inspection.
The Closure Compiler can use data type information about JavaScript variables to provide enhanced optimization and warnings. JavaScript, however, has no way to declare types.
Because JavaScript has no syntax for declaring the type of a variable, you must use comments in the code to specify the data type.
(The following is untested.)
Closure Compiler is reporting that in Dog.js it does not recognise the "type" Animal. This is because you are exporting an unnamed class expression: export default class.
So you could give your class a name (export default class Animal) and Closure Compiler may recognise the token Animal when it is consumed in Dog.js.
And you can also give your class a JSDoc that marks it as a #constructor:
/**
* Animal.
* #constructor
*/
export default class Animal {}

Related

How to declare and init nested enum with reserved keyword as type name in Swift?

I'm having a hard time to figure out how to declare a certain nested enum and calling one of it's automatic constructors. This enum i'm trying to declare is supposed to have a reserved keyword as type name.
Here is a simplified example of what i'm trying to do:
import Foundation
public class Foo {}
public extension Foo {
enum `Type`: Int {
case bar
}
}
var type: Foo.`Type`
type = Foo.`Type`(rawValue: 0)
This doesn't compile in Swift 5.2 with error
error: type 'Foo.Type' has no member 'init'
I'm pretty sure it is just a matter of getting the syntax right but i just can't figure it out. Anyone can please explain how to do it or is it just impossible all together?
There is no way to do this specific thing you want to do. That's why nobody uses nested types named Type, even though we all want to—the language already provides this type, and you don't get to override it with your own. We all use the Objective-C style naming of just smashing the word Type right up there without a proper delimiter.
FooType is what you've got to work with.

Mark Haxe Class for forced extend?

Is there a compiler meta for Class declaration, that prevents creating Class instance before extending it? In other words - some sort of opposite of #:final meta.
Like so (last line of code):
class A {
// ...
}
class B extends A {
// ...
}
// ...
var b = new B(); // OK
var a = new A(); // induce compiler-error
Simply don't declare a constructor at all for class A
Both the other answers are correct (no constructor or private constructor), but there are a few more details that you may interest you:
Here's an example of no constructor. Of note is that A simply doesn't have a constructor, and B simply doesn't call super(). Other than that, everything else works as you'd expect.
Here's an example of a private constructor. You still can't instantiate a new A(), but you do still need to call super() from B's constructor.
Technicalities:
Use of some features (like a default value on a member variable) will cause A to get an implicit constructor, automatically. Don't worry, this doesn't affect constructability or whether you need to call super(). But know that it is there, and if necessary an implicit super() call is prepended to B's constructor. See the JS output to verify this.
In any case, know that you can still instantiate an A at runtime with var a = Type.createInstance(A,[]); as compile-time type checks do not limit RTTI.
Related discussion:
Aside from private/no constructor, Haxe doesn't have a formal notion of abstract classes1 (base classes not expected to be instantiated) or abstract methods2 (functions on abstract base classes with no implementation that must be implemented by a derived class.) However, Andy Li wrote a macro for enforcing some of those concepts if you use them. Such a macro can detect violations of these rules and throw compile-time errors.
1. Not to be confused with Haxe abstracts types, which are an entirely different topic.
2. Not to be confused with virtual functions, which wikipedia describes as a function which can be overridden (though various docs for various languages describe this highly loaded term differently.)
One way of achieving this is to create private Class constructor:
class A {
private function new() {
// ...
}
}
// ...
var a = new A(); // Error: Cannot access private constructor

How to properly set up a class that inherits from another in Scala?

I have been looking at examples online, and tutorials, and I cannot find anything that explains how this (inheritance) differs from java. Simple example:
class Shape {
String type;
Shape(String type) {
this.type = type;
}
...
}
class Square extends Shape {
Square(String name){
Super(name);
}
....
}
Whats confusing me is in the above example I need to call the super class in order to set the 'type' variable, as well as to access it to tell me the Box objects' type as well. In Scala, how can this be done? I know scala uses traits interfaces as well, but is the above example omitted completely from scala? Can anyone direct me to a good example or explain it. I really appreciate it.
You can write almost exactly the same thing in Scala, much more concisely:
class Shape(var `type`: String)
class Square(name: String) extends Shape(name)
In the first line, the fact that type is preceded by var makes the compiler add getters and setters (from "5.3 Class Definitions" in the specification):
If a formal parameter declaration x : T is preceded by a val or
var keyword, an accessor (getter) definition (§4.2) for this parameter is implicitly added to the class. The getter introduces a value member x of class c that is defined as an alias of the parameter. If the introducing keyword is var, a setter accessor x _= (§4.2) is also implicitly added to the class.
In the second line name is not preceded by val or var, and is therefore just a constructor parameter, which is this case we pass on to the superclass constructor in the extends clause. No getters or setters are added for name, so if we created an instance square of Square and called square.name, it wouldn't compile.
Note also that type is a keyword in Scala, so I've had to surround it by backticks in both the definition and the example above:
Example 1.1.2 Backquote-enclosed strings are a solution when one needs to access Java identifiers that are reserved words in Scala.
There are many, many resource that you can read for more information about inheritance in Scala. See for example Chapters 4 and 5 of Programming Scala.

How do I force the Scala compiler to tell me when my class is abstract?

Why is the "abstract" keyword for class definition optional in Scala, and how do I force the Scala compiler to tell me when my class is abstract?
Here an example that I wrote in Eclipse:
class Toto[T] {
def get(index: Int): T
}
object Toto {
def create[T]: Toto[T] = new Toto[T]
}
This seems to be a perfectly valid class definition in Scala, although it does NOT define the required get method, and is NOT prefixed with abstract. If you don't need the abstract keyword, then why does it exist? And if you want to be told that your class is actually abstract, how do you get the compiler to tell you?
This is not valid scala code, abstract is required, and instanciation forbidden. From the spec (5.2, p63):
The abstract modifier is used in class
definitions. It is redundant for
traits, and mandatory for all other
classes which have incomplete members.
Ab- stract classes cannot be
instantiated (§6.10) with a
constructor invocation unless
followed by mixins and/or a refinement
which override all incomplete members
of the class. Only abstract classes
and traits can have abstract term
members.
The code produces an error in the REPL : error: class Toto needs to be abstract, since method get is not defined
I get the proper behavior with the same message in Eclipse too. You should check whether you get the same error with and without eclipse. Whichever is true, I guess if you have exactly the code you posted without an error (does it run?), a bug repport will be warranted.
To answer my own question: In Eclipse, you can only tell if a class is correct if all other classes compile without errors! In other word, you can't trust anything Eclipse says about a class unless there are no errors in other classes.
So if you have errors in several classes, then there is no way of knowing which ones are the real errors, and neither if a class without errors is correct.
You just have to repeatedly loop on the errors, fixing any one that makes sense, and hoping the others errors that don't make sense are eventually going to just disappear.

Bug in eclipse compiler or javac?

Who is right? Eclipse or javac?
--------------- c/v/A.java ---------------
package c.v;
public class A<T> {
}
--------------- c/v/B.java ---------------
package c.v;
public class B extends A<B.Secret> {
private class Secret {};
}
Eclipse compiles B.java just fine.
Javac has a problem.
$ javac c/v/B.java
c/v/B.java:3: c.v.B.Secret has private access in c.v.B
public class B extends A<B.Secret> {
^
1 error
The relevant parts of the Java Language Specification must be:
§8.1.4:
[...] The ClassType must name an accessible (§6.6) class type, or a compile-time error occurs.
§6.6.1:
[...]
A member (class, interface, field, or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if the type is accessible and the member or constructor is declared to permit access:
If the member or constructor is declared public, then access is permitted. All members of interfaces are implicitly public.
[...]
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
So since the ClassType is not within the body of the class, B.Secret is not accessible at this location, so A<B.Secret> is not accesible, so a compile-time error should occur.
Eclipse is wrong. If you advertise something as
extends A<X>
you need both to know about A, and X.
I would tend to think javac is right. In order to create a new class
A<B.Secret>
the generic needs to have access to the class it uses. The fact that B then extends that class is minor.