Why does Java require annotation values to be qualified in annotations but not in switch statements? - javac

In Java, Enum constants in a switch statement do not require (or even allow) the constants to be type-qualified.
Example:
switch (obj.getEnumValue()) {
case VALUE1:
...
case VALUE2:
...
}
This is possible of course because the Enum type is known at compile time.
However, the same convenience is not afforded to Enum values when used within annotations, even though the Enum type is known at compile time there too:
Example:
#Retention(RUNTIME) // compile error here!
public #interface MyAnnotation {
...
}
My question is why does the JLS treat these two cases differently? I'm trying to understand the reasoning from a language design perspective.
It seems like the same logic would apply in both cases: the Enum type is known, so the language should allow (or even require) the Enum constants to be unqualified, for the sake of brevity and programmer convenience.
PS. This is not a question about how to workaround the issue. This is a JLS design question.

Related

Why does dart not allow method overloading?

I tried to use method overloading in some dart code and quickly learned that overloading is not offered in dart.
My questions are: why is it not offered, and what is the recommended alternative? Is there a standard naming convention since methods that do the same thing but with different inputs must have different names?
Is it standard to use named parameters and then check that the caller has supplied enough information to complete the calculation?
Say I have a method that returns how much money someone makes in a year, called yearlyIncome.
In Java, I would create a method like this
double yearlyIncome(double hourlyRate, double hoursWorkedPerYear)
And maybe another method like this
double yearlyIncome(double monthlyRate, int monthsWorkedPerYear)
and so on. They're all used to calculate the same thing, but with different inputs. What's the best, standardized way to do this in dart?
Thanks so much in advance.
Function overloading is not supported in Dart at all.
Function overloading requires static types. Dart at its core is a dynamically typed language.
You can either use different names for the methods or optional named or unnamed parameters
// optional unnamed
void foo(int a, [String b]);
foo(5);
foo(5, 'bar');
// optional named
void foo(int a, {String b});
foo(5);
foo(5, b :'bar');
Optional parameters can also have default values. Optional named and unnamed parameters can not be used together (only one or the other for a single function)
In the case of a constructor you can use named constructors as an alternative
Dart did not support overloading originally because it was a much more dynamic language where the declared types did not have any semantic effect. That made it impossible to use static type based overload resolution.
Dart has since changed to be more statically type, and there is nothing fundamentally preventing Dart from adding overloading today, except that it would be a huge work and a huge change to the language. Or so I'd assume, because there isn't any obvious design that isn't either highly complicated or hugely breaking.
What you do instead in Dart is to use optional parameters. A method like:
String toString([int radix]);
effectively have two signatures: String Function() and String Function(int). It can act at both signatures.
There are definite limits to how far you can go with just optional parameters, because they still need to have exactly one type each, but that is the alternative that Dart currently provides. (Or use different names, but that's not overloading, you can do that in languages with overloading too).
Optional parameters is also one of the complications if we wanted to add overloading to the Dart language - would existing functions with optional parameters would count as multiple overloadings? If you declare a class like:
abstract class WithOverloading {
String toString();
String toString(int radix);
}
is that then the same signature as:
abstract class WithoutOverloading {
String toString([int radix]);
}
Probably not because you can tear off the latter and get one function with an optional parameter, and you might not be able to tear off both functions from the former and combine them into one function. Or maybe you can, that's why it's not a trivial design question how to include overloading into the existing Dart language.

Discussion Question: Why doesn't dart allow to declare enums in class?

I tried to declare an enum inside the class and it gave me an error stating can't have enum inside a class. I wanted to know the reason why but I didn't find anything on the internet. Declaring enum inside a class is allowed by major languages why not dart?
Dart does not allow nested type declarations in general. You can only declare types at top-level. This includes classes, mixins, typedefs and enums.
I believe the original reason was that it was not necessary, and implementing it inadequately was worse than not doing allowing it at all.
There is nothing inherently preventing Dart from allowing static types declared inside other types. Obviously, if Dart allowed classes statically declared inside classes, it would allow in arbitrary nesting of classes, so it really is a matter of allowing zero, one or an infinite amount of nesting. Dart currently has "one'.
Still, it's something that can be easily remedied if deemed wort the effort and a higher priority than other language changes.
The other option is to have non static nested types. That's a much bigger can of worms, and probably not something that's going to happen any time soon, if ever.
Dart doesn't allow declaring of Enum inside the class as far as I know. I've made that error before and it took me a minute to figure out what was wrong with my code. Declare/setup your Enum before your class like so:
enum Gender {
male,
female,
}
/// Then declare your class next
class MyClass {
/// The rest of your code goes here, and you still have access to your enum
}

Do you usually use class or struct to define a list of utility functions?

In Java, it is very common to have a list of utility functions
public class Utils {
private Utils() {
}
public static void doSomething() {
System.out.println("Utils")
}
}
If I were in Swift, should I use class or struct to achieve the similar thing? Or, it really doesn't matter?
class
class Utils {
private init() {
}
static func doSomething() {
print("class Utils")
}
}
struct
struct Utils {
private init() {
}
static func doSomething() {
print("struct Utils")
}
}
I think a conversation about this has to start with an understanding of dependancy injection, what it is and what problem it solves.
Dependancy Injection
Programming is all about the assembly of small components into every-more-abstract assemblies that do cool things. That's fine, but large assemblies are hard to test, because they're very complex. Ideally, we want to test the small components, and the way they fit together, rather than testing entire assemblies.
To that end, unit and integration tests are incredibly useful. However, every global function call (including direct calls to static functions, which are really just global functions in a nice little namespace) is a liability. It's a fixed junction with no seam that can be cut apart by a unit test. For example, if you have a view controller that directly calls a sort method, you have no way to test your view controller in isolation of the sort method. There's a few consequences of this:
Your unit tests take longer, because they test dependancies multiple times (e.g. the sort method is tested by every piece of code that uses it). This disincentivizes running them regularly, which is a big deal.
Your unit tests become worse at isolating issues. Broke the sort method? Now half your tests are failing (everything that transitively depends on the sort method). Hunting down the issue is harder than if only a single test-case failed.
Dynamic dispatch introduces seams. Seams are points of configurability in the code. Where one implementation can be changed taken out, and another one put in. For example, you might want to have a an MockDataStore, a BetaDataStore, and a ProdDataStore, which is picked depending on the environment. If all 3 of these types conform to a common protocol, than dependant code could be written to depend on the protocol that allows these different implementations to be swapped around as necessary.
To this end, for code that you want to be able to isolate out, you never want to use global functions (like foo()), or direct calls to static functinos (which are effectively just global functions in a namespace), like FooUtils.foo(). If you want to replace foo() with foo2() or FooUtils.foo() with BarUtils.foo(), you can't.
Dependancy injection is the practice of "injecting" dependancies (depending on a configuration, rather than hard coding them. Rather than hard-coding a dependancy on FooUtils.foo(), you make a Fooable interface, which requires a function foo. In the dependant code (the type that will call foo), you will store an instance member of type Fooable. When you need to call foo, call self.myFoo.foo(). This way, you will be calling whatever implementation of Fooable has been provided ("injected") to the self instance at the time of its construction. It could be a MockFoo, a NoOpFoo, a ProdFoo, it doesn't care. All it knows is that its myFoo member has a foo function, and that it can be called to take care of all of it's foo needs.
The same thing above could also be achieve a base-class/sub-class relationship, which for these intents and purposes acts just like a protocol/conforming-type relationship.
The tools of the trade
As you noticed, Swift gives much more flexibility in Java. When writing a function, you have the option to use:
A global function
An instance function (of a struct, class, or enum)
A static function (of a struct, class, or enum)
A class function (of a class)
There is a time and a place where each is appropriate. Java shoves options 2 and 3 down your throat (mainly option 2), whereas Swift lets you lean on your own judgement more often. I'll talk about each case, when you might want to use it, and when you might not.
1) Global functions
These can be useful for one-of utility functions, where there isn't much benefit to " grouping" them in a particular way.
Pros:
Short names due to unqualified access (can access foo, rather than FooUtils.foo)
Short to write
Cons:
Pollutes the global name space, and makes auto-completion less useful.
Not grouped in a way that aids discoverability
Cannot be dependancy injected
Any accessed state must be global state, which is almost always a recipe for a disaster
2) Instance functions
Pros:
Group related operations under a common namespace
Have access to localized state (the members of self), which is almost always preferable over global state.
Can be dependancy injected
Can be overridden by subclasses
Cons:
Longer to write than global functions
Sometimes instances don't make sense. E.g. if you have to make an empty MathUtils object, just to use its pow instance method, which doesn't actually use any instance data (e.g. MathUtils().pow(2, 2))
3) Static functions
Pros:
Group related operations under a common namespace
Can be dependancy in Swift (where protocols can support the requirement for static functions, subscripts, and properties)
Cons:
Longer to write than global functions
It's hard to extend these to be stateful in the future. Once a function is written as static, it requires an API-breaking change to turn it into an instance function, which is necessary if the need for instance state ever arrises.
4) Class functions
For classes, static func is like final class func. These are supported in Java, but in Swift you can also have non-finals class functions. The only difference here is that they support overriding (by a subclass). All other pro/cons are shared with static functions.
Which one should I use?
It depends.
If the piece you're programming is one that would like to isolate for testing, then global functions aren't a candidate. You have to use either protocol or inheritance based dependancy injection. Static functions could be appropriate if the code does not nned to have some sort of instance state (and is never expected to need it), whereas an instance function should be when instance state is needed. If you're not sure, you should opt for an instance function, because as mentioned earlier, transitioning a function from static to instance is an API breaking change, and one that you would want to avoid if possible.
If the new piece is really simple, perhaps it could be a global function. E.g. print, min, abs, isKnownUniquelyReferenced, etc. But only if there's no grouping that makes sense. There are exceptions to look out for:
If your code repeats a common prefix, naming pattern, etc., that's a strong indication that a logical grouping exists, which could be better expressed as unification under a common namespace. For example:
func formatDecimal(_: Decimal) -> String { ... }
func formatCurrency(_: Price) -> String { ... }
func formatDate(_: Date) -> String { ... }
func formatDistance(_: Measurement<Distance>) -> String { ... }
Could be better expressed if these functions were grouped under a common umbrella. In this case, we don't need instance state, so we don't need to use instance methods. Additionally, it would make sense to have an instance of FormattingUtils (since it has no state, and nothing that could use that state), so outlawing the creation of instances is probably a good idea. An empty enum does just that.
enum FormatUtils {
func formatDecimal(_: Decimal) -> String { ... }
func formatCurrency(_: Price) -> String { ... }
func formatDate(_: Date) -> String { ... }
func formatDistance(_: Measurement<Distance>) -> String { ... }
}
Not only does this logical grouping "make sense", it also has the added benefit of bringing you one step closer to supporting dependancy injection for this type. All you would need is to extract the interface into a new FormatterUtils protocol, rename this type to ProdFormatterUtils, and change dependant code to rely on the protocol rather than the concrete type.
If you find that you have code like in case 1, but also find yourself repeating the same parameter in each function, that's a very strong indication that you have a type abstraction just waiting to be discovered. Consider this example:
func enableLED(pin: Int) { ... }
func disableLED(pin: Int) { ... }
func checkLEDStatus(pin: Int) -> Bool { ... }
Not only can we apply the refactoring from point 1 above, but we can also notice that pin: Int is a repeated parameter, which could be better expressed as an instance of a type. Compare:
class LED { // or struct/enum, depending on the situation.
let pin: Int
init(pin: Int)? {
guard pinNumberIsValid(pin) else { return nil }
self.pin = pin
}
func enable() { ... }
func disable() { ... }
func status() -> Bool { ... }
}
Compared to the refactoring from point 1, this changes the call site from
LEDUtils.enableLED(pin: 1)`
LEDUtils.disableLED(pin: 1)`
to
guard let redLED = LED(pin: 1) else { fatalError("Invalid LED pin!") }
redLED.enable();
redLED.disable();
Not only is this nicer, but now we have a way to clearly distinguish functions that expect any old integer, and those which expect an LED pin's number, by using Int vs LED. We also give a central place for all LED-related operations, and a central point at which we can validate that a pin number is indeed valid. You know that if you have an instance of LED provided to you, the pin is valid. You don't need to check it for yourself, because you can rely on it already having been checked (otherwise this LED instance wouldn't exist).

In Dart's Strong-Mode, can I leave off types from function definitions?

For example, I'd like to just be able to write:
class Dog {
final String name;
Dog(this.name);
bark() => 'Woof woof said $name';
}
But have #Dog.bark's type definition be () => String.
This previously wasn't possible in Dart 1.x, but I'm hoping type inference can save the day and avoid having to type trivial functions where the return type is inferable (the same as it does for closures today?)
The language team doesn't currently have any plans to do inference on member return types based on their bodies. There are definitely cases like this where it would be nice, but there are other cases (like recursive methods) where it doesn't work.
With inference, we have to balance a few opposing forces:
Having smart inference that handles lots of different cases to alleviate as much typing pain as we can.
Having some explicit type annotations so that things like API boundaries are well-defined. If you change a method body and that changes the inferred return type, now you've made a potentially breaking change to your API.
Having a simple boundary between code that is inferred and code that is not so that users can easily reason about which parts of their code are type safe and which need more attention.
The case you bring up is right at the intersection of those. Personally, I lean towards not inferring. I like my class APIs to be pretty explicitly typed anyway, since I find it makes them easier to read and maintain.
Keep in mind that there are similar cases where inference does come into play:
Dart will infer the return type of an anonymous function based on its body. That makes things like lambdas passed to map() do what you want.
It will infer the return type of a method override from the method it is overriding. You don't need to annotate the return type in Beagle.bark() here:
class Dog {
String bark() => "Bark!";
}
class Beagle extends Dog {
final String name;
Dog(this.name);
bark() => 'Woof woof said $name';
}

What are the conventions in Dart about class members' encapsulation and type annotations?

I am new to Dart language. So I would like to know more about some conventions that programmers follow while developing in this language.
Should I always encapsulate my class members as I do, for example in Java? Whenever I create property of class, should I make it private and provide getters/setters? Or there are situations when I should leave them public? If so, what are examples of these situations?
In my opinion, type annotations such as String, int, etc. increase readability of code. They serve as a documentation for other developers who are reading/using my code. Programmer should not think value of what type is storing in this variable right now. So again, what are the situations, that require using var keyword when declaring a variable?
Dmitry.
Thank you.
Thanks for checking out Dart!
No need to encapsulate class fields. Dart creates implicit getters and setters for you. If you need to actually compute something for that field, you can then implement the getter or setter manually. Bonus: this doesn't break consumers of your API.
Example:
class Person {
int age;
}
Later, you want to calculate age:
class Person {
DateTime birthdate;
int get age => new DateTime.now().difference(birthdate).inDays ~/ 365;
}
In both cases, you can do this:
print(person.age);
Pretty cool! No change in API, and no defensive getters and setters (just add them when you need them).
You should use type annotations for the "surface area" of your code. For example, use type annotations for method and function signatures. For cases where the variable's type is very obvious, you should consider using var, because it's more terse and readable.
For example:
String doCoolStuff(int bar) {
var clearlyABool = true;
return 'Hello world';
}
Note that the return type and bar parameter are type annotated, but the clearlyABool uses var because we initialize with a bool.
Feel free to use type annotations everywhere, it's programmer choice. Anecdote: the dart2js source code uses type annotations pretty much everywhere.

Resources