Flutter: final field must be a one of the following - string

We have a widget class that has a final property of this.type. Currently this is a String and if the String matches one of the available types it returns the correct content via that widget’s builder.
Is there a way that instead of asking for a String, we ask for one of the available potential options.
Eg. Only Block, Fixed or None are acceptable strings. Can we make sure that the use of this widget can only accept those terms.

You can use enums. First declare an enum using the enum keyword:
enum AcceptableOptions { Block, Fixed, None }
Then in your widget, use AcceptableOptions instead of String
class TestWidget extends StatelessWidget {
const TestWidget({
required AcceptableOptions option,
});
#override
Widget build(BuildContext context) {
return Container();
}
}
TestWidget(option:AcceptableOptions.Block)

Related

Overriding parent methods with contravariant arguments

Basically, I want to override a parent class with different arguments. For example:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
Then override that class, something like:
class HoldMore extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
set(value, value2);
}
override public function set(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
Obviously this will return an error, Field set overloads parent class with different or incomplete type. Is there a way around this? I tried using a public dynamic function, and then setting set in the new() function, but that gave a very similar error. Any thoughts?
This is just a complement to #stroncium's answer, which is totally correct.
Here is an example how it could look like:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
class HoldMore<T> extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
setBoth(value, value2);
}
// you cannot override "set" with a different signature
public function setBoth(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
alternatively, you could use an array as parameter or a dynamic object holding multiple values in order to "set" them using the same method, but you loose some of the compiler's type checking.
If you wrote the base class you could add an optional argument to it, this would be a workaround though, not directly what you want to do.
In the current state it totally won't work. There is not only 1 problem, but few of them:
Type T is meaningless in context of this new class, you should either use some concrete type or template this class over T.
You can not change the number of arguments of function when overriding it. However you can add another function(with a different name) to accept 2 arguments and do what you want (which is the way you would use in most languages, by the way).
I don't really understand how you see a contravariance problem there. The actual problem is that haxe doesn't support function overload. (It actually does, the function signature is name + full type, but that's not what you would want to write nor support, and is mostly used for js/java externs.)
Unfortunately the language doesn't allow it.

ValueConverter for String to String

I need to perform additional modifying of all Strings, is it possible to make a ValueConverter with a Target Type of String, or if not, in what other way can I do it?
class StringValueConverter implements ValueConverter {
#Override
boolean canConvert(Object value) {
value instanceof String
}
#Override
Object convert(Object value) {
//modifying value
}
#Override
Class<?> getTargetType() {
return String
}
}
I need to do it before binding
In Groovy yes you can. There are various ways:
Using Extension Module is one of them.
Another way would be to use runtime metaprogramming, for example:
String.metaClass.flip = {
delegate.reverse()
}
assert "Hello".flip() == "olleH"
Above is a contrived example of adding methods to metaClass of String, but a convert method as in your example can fit in as well.
However, the extension module is what can be robust in your case if you are looking for adding sanity by canConvert which would not be needed for runtime metaClass methods as they are only available for String class.

Groovy - can a method defined in an Interface have default values?

If the following is entered in Eclipse/STS (with groovy):
interface iFaceWithAnIssue {
def thisIsFine(a,b,c)
def thisHasProblems(alpha='va')
}
The only line that complains is the one trying to use a default value. I can not tell from the codehaus site if this is supported or not.
The IDE error is:
Groovy:Cannot specify default value for method parameter
So this makes me think it is not supported. As there will be multiple implementations, I wanted to use an interface here. I don't really need the default value in the interface, but there is an error trying to fulfill the interface contract if the implementation class then tries to default this argument. Is there any way?
No, you cannot.
When you define a default value, Groovy actually creates multiple methods in your class, so for example:
class Test {
void something( a=false ) {
println a
}
}
Actually creates
public void something(java.lang.Object a) {
this.println(a)
}
and
public void something() {
this.something(((false) as java.lang.Object))
}
This can't be done as it stands in Interfaces.
You could do:
interface iFaceWithAnIssue {
def thisHasProblems()
def thisHasProblems(alpha)
}
Then
class Test implements iFaceWithAnIssue {
// This covers both Inteface methods
def thisHasProblems(alpha='va') {
// do something
}
}

Generic used in conjunction with Sort(Comparison<T>)

Im wondering if its possible to reuse my overload of the Sort(Comparison) method to sort both labels and textboxes by tabIndex. Ive already tried and i couldnt get it to work. Any help would be appreciated.
foreach(Control control in gbUserInputs.Controls)
{
if (control is Label)
{
inputLabels.Add((Label)control);
}
if (control is TextBox)
{
inputTxtboxes.Add((TextBox)control);
}
}
Sort method call(this doesnt work).
inputLabels.Sort(sortMyInputs<Label>);
Overload of sort method.
private static int sortMyInputs<T>(T entry1, T entry2)
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
You shouldn't be making a generic method:
private static int CompareLabels(Label entry1, Label entry2)
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
The point of a generic delegate is to allow it to hold methods of different concrete types; not to allow it to hold methods that are themselves generic.
If you want to reuse your method, you can modify it to take Control (which both TextBox and Label inherit); you would still be able to pass it to List<Label>.Sort because of delegate covariance.
If you're using .Net < 4, which doesn't have delegate covariance, you can do it your way by adding a constraint to the method so that it knows what T can be:
private static int CompareLabels<T>(T entry1, T entry2) where T : Control
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
You can also simply replace all of your code with one line of LINQ:
inputLabels = gbUserInputs.Controls.OfType<Label>()
.OrderBy(c => c.TabIndex)
.ToList();

how to include a Check in the Lwuit command?

Hi I want to include a check (as in a tick mark) besides the command on the display screen.IS there any way I can implement it?
You can create the new class with implement the ListCellRenderer interface or extend with DefaultListCellRenderer class. Then implement all abstract methods and override getListCellRendererComponent method like this,
public Component getListCellRendererComponent(List list, Object value,
int index, boolean isSelected) {
if (isSelected && list.hasFocus()) {
// do selected style that means selected command style
} else {
// do unselected style that means unselected command style
}
return this;
}
For your reference see this link.
Finally you need to pass this renderer class to setMenuRenderer method.
For single form means do like this,
Form form = new Form();
form.setMenuRenderer(new MenuRenderer()); // pass your created render class
For all form means do like this,
UIManager.getInstance().getLookAndFeel()
.setMenuRenderer(new MenuRenderer()); // pass your created render class

Resources