I have a variable which I want to give the option to call the setter with multiple types, but I would set the variable with one type of course. For example, if I have a variable called list, I want to be able to call the setter using a single list item i.e. a string and then in the setter method I would add the string to the end of the list. Another way to set the variable would be through an actual list, and the setter, I would just set the list to the list passed in.
Here's an example of what I would like to do, but the second time I call the list setter method, I get an error saying The name 'list' is already defined:
List<String> _list = [];
List<String> get list => list;
set list(List<String> newList) {
_list = newList;
}
set list(String newListItem) {
_list = [..._list, newListItem];
}
As Remi mentioned, it is not possible to do so. I would argue that it would be best not to do so because it changes the expectation of the contract of the setter. That is, you expect a setter to replace the value of a variable. Having a setter that appends to it is counter-intuitive and will lead to confusion for other developers.
Generally, for the maintainability of a code base, it's better to have an explicit interface to your class's behavior than to provide terse shortcuts.
That is not possible.
In Dart you can have only one setter per variable.
You will need to rename one of your setters to use a different name.
Related
I use this getter to make a list:
List<CabModel> get cabs() => cabsList.value;
and works. But now I need to pass a parameter to filter a list. Something like
List<CabModel> get cabs(String value) => cabsList.value;
I know, I can't pass parameter in getters, but how do it?
The getter only sends back copy of data, but cannot make any changes/filter stuff. You'd have to create a function that takes in the required parameters and returns the required value.
If you also want to filter and overwrite the existing data, make a setter as well.
List FilteredList(...){
.../required filtering
return list
}
What is the reason of using custom getters and setters in an application.
That's fairly very simple
First let me show you a sample of how getters and setters in Dart look like, which is essentially the language behind Flutter
class Foo {
// Creating a field/instance variable
String _fooName; //Keeping it private always
// Using the getter
String get foo_name {
//We can do something else here, like saving the variable somewhere and then returning it to the caller function
return _fooName;// private variable return for use in outside class
}
// Using the setter method
set foo_name (String name) {
// We can do something else, like update another variable based on fooName
this._fooName = name;//private variable being assigned new value
}
}
From the name, setters are involved in setting the values to an instance variable in an object oriented programming paradigm whereas getters are involved in getting the value of an instance variable
Now you would ask why not return the instance variable directly and why having such a roundabout approach to setting and getting the value
Well the answer is while getting as well as setting, we might want to do some other operation too other than just setting or getting the value and it's always better not to give admin access to the variables and that's why they are private so as to promote consistency within the objects accessing the field
It's a matter of preference, but you really shouldn't needlessly create one for a single field
https://dart.dev/guides/language/effective-dart/usage#dont-wrap-a-field-in-a-getter-and-setter-unnecessarily
One use case for creating a setter would be to perform some type of validation
For a getter, it'd be useful for a calculated field based on other properties, rather than a single property alone
Often times I have an instance field that needs to be initialized in a constructor. For example, it might be needed to be calculated based on other instance fields, hence I can't initialize it inline (where declared) or with a constructor initializer list.
But it either has to be nullable, or declared late, if I need to initialize it in constructor. The rationale behind late keyword is that programmer states "I'll initialize this before using, trust me", when it can not be determined by the compiler that initialization will take place before first usage. BUT: this "programmer guarantee" seems A) terrible and B) unnecessary in case of constructors, because it can be determined by compiler whether the field was initialized in a constructor (and constructor itself is obviously guaranteed to execute before any other instance methods).
Obvious downside to using late fields in such scenarios is that nothing enforces them compile-time to be actually initialized during construction (or anywhere, for that matter). Plus, every time the late field is read, a runtime check is inserted to make sure it has been assigned a value - I don't need that when I initialize in constructors.
Therefore, it seems that, technically it should be possible to have non-nullable non-late fields that are initialized within a constructor body (and if they are not - compiler can throw an error).
So what is the rationale of requiring constructor-initialized fields to be either nullable, or declared as late? Is there a technical reason why this limitation is imposed, or is it just a design oversight by the Dart team?
Dart executes constructor bodies inside-out, from base class to derived class. This allows virtual dispatch to occur in the constructor body. The fact that virtual dispatch can occur in the constructor body means that the compiler cannot statically determine what code will be executed by the constructor body, and therefore it cannot deduce what the constructor body might ultimately initialize.
That the constructor body can execute arbitrary code (including callbacks) that might initialize members or that might depend on initialized members makes it even more complicated.
Furthermore, allowing members to be not initialized when the constructor body runs would be error-prone and a source for confusion. For example, with:
class SomeClass {
int member;
SomeClass() {
updateMember(0);
}
void updateMember(int value) {
print(value); // Oops.
member = value;
}
}
With Dart's current design, all instance methods (and their overrides) can be guaranteed that members are initialized when the method is called. If members were allowed to be uninitialized when the constructor body is executed, that would not longer be true, and all instance methods then would need to consider if they might be invoked from the constructor (or from a base class constructor), possibly indirectly from other method calls, and whether accessed members might not be initialized yet.
(I'll grant that that previous point isn't terribly strong since it currently can still happen that a member is initialized to an object that the constructor body must mutate, but typically instance methods receiving an empty List, Map, etc. is less of a problem than receiving uninitialized members. The above situation also could happen with late members, but that's the baggage that comes with choosing to use late.)
Null-safety disallows the possibility of accessing uninitialized non-late variables, but your proposal would make that possible.
Also, because there is a distinction between initializing members via an initializer list and via a constructor body, people are encouraged to use initializer lists when possible.
The point that you are ignoring here is that when you want to pass a variable to a constructor you will definitely initialize it, otherwise you wouldn't be able to use that widget because you have to pass the variables needed to its constructor. so this late or nullable keywords can be used for the values that you are trying to pass to a widget and not in the widget itself that you are passing them to, but before it.
I have created a custom class and I want to add associated getters and setters. I have read the official documentation from Apple and notice that when setting a getter and setter, you actually create a separate variable, which seems really confusing. For instance, in the documentation linked above, getters and setters are applied to a new variable called perimeter to obtain values from another variable called sidelength. Below is my code:
Getters and setters like you are implementing them are only used for computed variables in Swift. A variable with a getter and setter doesn't actually store anything, but does something when assigned or used for its value with other variables. When appropriate to use, the usage would be more like this.
var _key: String?
var key: String? {
get {
return _key
}
set {
_key = newValue
}
}
You would rarely if ever use this on an identical data type though. I use these for communication with CoreData often, and setting things like dates as a string or back to a date. Occasionally I might use it to handle the change in an optional to a non optional.
Getters and setters are not needed in order to use the variable in Swift though. If you are used to languages with them, I can understand the confusion here, but forget the correlation and start over with how you think about it. I am sure after a short amount of time, you will like the way Swift works with its datatypes!
Edit:
In order to do what you want, all you need is this:
class PollCell: UICollectionViewCell {
var key: String?
}
Now you can assign any value you want to cell.key and retrieve any value you want from cell.key.
1.First I defined an extension method for the IEnumerable.Add() like the code below
public static IEnumerable<T> Add<T, TKey>(this IEnumerable<T> enumerable, T value, Func<T, TKey> orderBy)
{
if (enumerable == null)
return null;
if (enumerable is IList<T>)
{
var list = enumerable as IList<T>;
if (!enumerable.Contains(value))
{
list.Add(value);
enumerable = enumerable.OrderBy(orderBy);
}
}
}
2.Then,I raised the extension method like this to sort the itemlist according to the "Date" property when a new item was added to the list:
itemList.Add(item, o => o.Date);
3.After all,it appears that the "itemList" was not sorted.
4.I followed the extension method and found that "enumerable" was a new instance after "enumerable = enumerable.OrderBy(orderBy)" and it was sorted,but the "list" was not.
5.Then I tried to cast the sorted enumerable to list like "list=enumerable.ToList()",both of them("enumerable" and "list") were sorted.
6.After that ,when the call stack went back to the "itemList.Add(item, o => o.Date);",the "itemList" was not sorted at all!!!
Anyone can give me some advices?Thanks a looooooooooooooooooooooooooooooooot!!
I believe your problem is that the reference to enumerable is being passed by value rather than by reference. See Jon Skeet's article about passing parameters by value or reference for more information about what that means. In short, C# passes a copy of the parameter's reference so assigning a new value to parameter does not change the reference of the object that was passed in. To pass a parameter by reference you specify the ref keyword, but I don't think that will work with an extension method. If you're dead set on making this work I would suggest inserting the items into your List in sorted order, probably requiring that T implement IComparable.
Update:
First off, see the Skeet's article it's really quite informative and I will probably only be half as clear as he is. Second, when you pass an object as a parameter to a method you are passing a copy of the reference. This means you can still access members of the object but, the same way that a value type is passed by copy, if you modify the reference (ie assign it a new value) you wont modify the original reference. Specifying ref means that you are passing a reference to the reference and changing the reference (assigning a value to it) will affect the original object.
Neither OrderBy or ToList will affect the source list. When you did this: list=enumerable.ToList() you changed your variable to point to a whole new list instance.
It appears to me that this method does too much. I would keep adding and sorting as separate operations. The fact that this extends IEnumerable but silently does nothing if the target is not an IList is a code smell.