{"componentChunkName":"component---src-templates-lesson-post-js","path":"/lesson/extending-classes-inheritance","result":{"data":{"strapiLesson":{"id":"Lesson_44","author":{"email":"eric@ericwindmill.com","username":"Eric Windmill","twitter":"ericwindmill"},"content":"You can _inherit from_ or _extend_ a class using the `extends` keyword. This allows you share properties and methods between classes that are similar, but not exactly the same. Also, it allows different _subtypes_ to share a common runtime type so that static analysis doesn't fail. (More on this below);\n\nThe classic example is using different types of animals.\n\n```run-dartpad:theme-light:run-false:split-60\nclass Animal {\n  Animal(this.name, this.age);\n  \n  int age;\n  String name;\n\n  void talk() {\n    print('grrrr');\n  }\n}\n\nclass Cat extends Animal {\n  // use the 'super' keyword to interact with \n  // the super class of Cat\n  Cat(String name, int age) : super(name, age);\n  \n  void talk() {\n    print('meow');\n  }\n  \n}\n\n\nclass Dog extends Animal {\n  // use the 'super' keyword to interact with \n  // the super class of Cat\n  Dog(String name, int age) : super(name, age);\n  \n  void talk() {\n    print('bark');\n  }\n  \n}\n\nvoid main() {\n  var cat = Cat(\"Phoebe\",1);\n  var dog = Dog(\"Cowboy\", 2);\n  \n  dog.talk();\n  cat.talk();\n}\n```\n\nHere, the Dog and Cat classes share the common properties of Animal, reducing the need to duplicate code in each class. But, it wouldn't make much sense if they both said \"meow\" when you called `talk`. So, talk is defined separately on the different classes, and is implemented correctly on each animal.\n\n### Some 'gotchas' with inheritance\n\nAs you'll see, inheritance is not without it's problems. What if you decided to change that 'talk' method to 'makeNoise'?\n \nYou now have to update the code for both the Cat and Dog API. If you didn't, then anywhere you call `Animal.talk` may fail. For instance, if you have code that doesn't care what _subtype_ of animal it gets, it just knows it needs to make that animal talk. \n\nThat's an example of the statement I made earlier about subtypes sharing super types. An object of type `Cat` _also_ is of type `Animal`. Therefor, Cat instances can be passed into functions that require `Animal` instances.\n\n```dart\nrecordAnimalNoise(Animal animal) {\n  _recordNoise(animal.talk());\n}\n\nmain() {\n  recordAnimalNoise(Cat('Wallace', 1)); // OK!\n  recordAnimalNoise(Dog('Lizard', 3)); // OK!\n}\n```\n\nThis problem can be solved using other features of Dart's classes, which are discussed in the next few examples.","updated_at":"Saturday, 18th of July, 2020","slug":"extending-classes-inheritance","strapiId":44,"title":"Extending classes (inheritance)","tutorial":{"category":"Dart","title":"Object-Oriented Programming"}},"strapiTutorial":{"lessons":[{"author":1,"content":"Constructors are used to create objects with pre-determined values for the properties. Constructors come in three flavors: the standard constructors, named constructors, and factory constructors. (Factory constructors are discussed on a different page.)\n\n\n```run-dartpad:theme-light:run-false:split-60\nclass Cat {\n    String name;\n    String color;\n    \n    // a simple constructor\n    Cat(this.name, this.color);\n\n    // named constructors are used to define additional constructors\n    // they return a new instance of the class, (but not with a 'return' statement) \n    // usually with some values given defined values.\n    Cat.orange(this.name) {\n        color = 'Orange';\n    }\n    \n    // this is another named constructor example\n    Cat.black(this.name) {\n        color = 'Black';\n    }\n  \n    @override\n    String toString() => \"Cat: ${this.name}, ${this.color}\";\n}\n\nvoid main() {\n    print(Cat('nora', 'orange'));\n    print(Cat.orange('nora'));\n    print(Cat.black('nora'));\n    print(Cat.fromJson({'name': 'Nora', 'color':'Orange'}));\n}\n ```","created_at":"2020-07-18T21:04:48.329Z","id":40,"slug":"constructors","title":"Constructors","tutorial":5,"updated_at":"2020-07-18T21:04:48.342Z"},{"author":1,"content":"The interface of an object is exposed via _instance properties_ and _instance methods_.\n\nThese are the most \"basic\" members on a class. \n\n### Properties\n\nProperties are variables of any type defined on the class. \n\n```dart\nclass Cat {\n  String name; // property\n  String color; // property\n  int age; // property\n}\n\n// useage:\nvar cat = Cat();\ncat.name = 'Wallace'; \nprint(cat.name);\n``` \n\n### Methods\n\nMethods are functions on a class that provide behavior for an object. _Instance methods_ on objects are exposed via instances of the class. They have access to other variables and methods on the instance, as well as the keyword `this`.\n\n```dart\nclass Cat {\n  String name; // property\n  String color; // property\n  int age; // property\n\n  void talk() {\n   print('meow!');\n  }\n}\n\n// useage:\nvar cat = Cat();\ncat.talk();\n```","created_at":"2020-07-18T21:05:32.147Z","id":41,"slug":"properties-and-methods","title":"Properties and methods","tutorial":5,"updated_at":"2020-07-18T21:05:32.157Z"},{"author":1,"content":"</code></pre>Factory constructors return am instance of the class, but it doesn't necessarily create a new instance. Factory constructors might return an instance that already exists, or a sub-class.\n\nRules for factory constructors:\n\n- Factory constructors _do_ use the `return` key word.\n- You cannot refer to 'this' within the factory constructor.\n\n<pre>\n    <code class=\"language-run-dartpad:theme-light:mode-dart:split-60:width-100%:height-600px\">\nclass Cat {\n    String name;\n    String color;\n \n    // factory constructor that returns a new instance \n    factory Cat.fromJson(Map json) {\n        return Cat(json['name'], json['color']);\n    }\n} \n","created_at":"2020-07-19T18:57:17.572Z","id":46,"slug":"factory-methods","title":"Factory methods","tutorial":5,"updated_at":"2020-07-19T19:20:46.854Z"},{"author":1,"content":"Class fields in Dart can be `final`. Marking a field as `final` tells Dart that this variable can never be re-assigned. Importantly, this doesn't mean that the variable must be declared and assigned at the same time. Often, you'll use the `final` keyword for class properties, and assign them a value in the constructor. \n\n```dart\nclass Rectangle {\n  // these are assigned in the constructor,\n  // and can never be changed.\n  final int width;\n  final int height;\n  \n  Rectangle(this.width, this.height);\n}\n``` \n\nSide note: This square is said to be _immutable_. All of it's field are final, so it cannot be changed once created.\n\n### Initializer Lists\n\nAn _initializer list_ allows you to assign properties to a new instance variables _before_ the constructor body runs, but after creation. This is handy when you want to set a final variables value, but the value isn't a compile-time constant. For instance:\n\n```run-dartpad:theme-light:run-false:split-60\n\nmain() {\n  final rectangle = Rectangle(2, 5);\n}\n\nclass Rectangle {\n  final int width;\n  final int height;\n  final int area;\n  \n  The area of the rectangle uses the `width` and `height`\n  variables, but cannot be done outside of the constructor\n  because the class doesn't know what the width and height\n  are equal to until an instance is created.\n  Rectangle(this.width, this.height) \n    : area = width * height {\n      print(area);\n    }\n}\n```\n","created_at":"2020-07-18T21:09:27.241Z","id":45,"slug":"initializer-lists-and-final-properties","title":"Initializer lists and final properties","tutorial":5,"updated_at":"2020-07-18T21:09:27.247Z"},{"author":1,"content":"The _singleton pattern_ is a pattern used in object-oriented programming which ensures that a class has only one instance and also provides a global point of access to it. Sometimes it's important for a class to have exactly one instance, or you might force your app into a weird state. For example, you only want one instance of a class that represents your local storage, or you may end up with two different sources of data, which are out of sync. For the same reason, an operating system should have exactly one file system.\n\nThe idea is that anywhere in your code that you call `MyClass()`, it will return the same instance of that class, with the same state, etc. Thanks to `factory` constructors, implementing the singleton pattern in Dart is not only possible, but simple and flexible. \n\n```dart\nclass FileSystemManager {\n  static final FileSystemManager _instance = FileSystemManager._internal();\n \n  // using a factory is important\n  // because it promises to return _an_ object of this type\n  // but it doesn't promise to make a new one.\n  factory FileSystemManager() {\n    return _instance();\n  }\n  \n  // This named constructor is the \"real\" constructor\n  // It'll be called exactly once, by the static property assignment above\n  // it's also private, so it can only be called in this class\n  FileSystemManager._internal() {\n    // initialization logic \n  }\n  \n  // rest of class as normal, for example:\n  void openFile() {}\n  void writeFile() {}\n}\n``` \n\nConsuming that class will make it more clear:\n\n```run-dartpad:theme-light:run-false:split-60\nvoid main() {\n  // This constructor calls the factory constructor,\n  // which turns around and returns the static instance\n  // which was initialized with the `_internal` named constructor\n\n  // this will be true if the two instances have the same hashcode\n  // (hint: they do)\n  print(FileSystemManager().hashCode == FileSystemManager().hashCode);\n} \n\nclass FileSystemManager {\n  static final FileSystemManager _instance = FileSystemManager._internal();\n\n  factory FileSystemManager() {\n    return _instance;\n  }\n  \n  FileSystemManager._internal() {\n    // initialization logic \n  }\n  \n  void openFile() {}\n  void writeFile() {}\n}\n```","created_at":"2020-07-19T18:57:46.352Z","id":47,"slug":"singletons","title":"Singletons","tutorial":5,"updated_at":"2020-07-19T18:57:46.358Z"},{"author":1,"content":"Nearly all the code you write in Dart will be contained in classes. And a class is a blueprint for an `object`. That is, a class describes an object that you can create. The object itself is what holds any specific data and logic. For example, a `Cat` class might look like this:\n\n```dart\nclass Cat {\n    String name;\n    String color;\n}\n```\n\nThe variable declarations above, `String name` and `String color`, are called _properties_ or _class members_. (NB: _Members_ can also refer to functions, getters and setters on classes.)\n\n### Instances of classes\n\nThis class describes an object that can be created, like this:\n\n```dart\nCat nora = new Cat(); // note: the `new` keyword is optional in Dart 2\nnora.name = 'Nora';\nnora.color = 'Orange';\n```\n\n\n<div class=\"aside\">\nA note about the (lack of) the new keyword:\n`\nIf you're coming from many other object-oriented languages, you've probably seen  the `new` keyword used to create new instances of a class. In Dart, this `new` keyword works the same way, but _it isn't necessary_. In Dart 2, you don't need to use `new` or `const` to create an object. The compiler will infer that for you.\n</div>\n\n\n```run-dartpad:theme-light:run-false:split-60\nclass Cat {\n    String name;\n    String color;\n}\n\nvoid main() {\n    var nora = Cat();\n    nora.name = 'Nora';\n    nora.color = 'Orange';\n\n    print(nora);\n    print(nora.name);\n    print(nora.color);\n}\n```","created_at":"2020-07-18T17:48:00.269Z","id":39,"slug":"classes","title":"Classes","tutorial":5,"updated_at":"2020-07-18T17:48:00.275Z"},{"author":1,"content":"<div class='aside'>\nThe following is an excerpt from the book <a href=\"https://www.manning.com/books/flutter-in-action\">Flutter in Action</a>.\n</div>\n\nModern applications basically all do the same thing: they give us (smart humans) a way to process and collaborate over large data sets. Some apps are about communication, like social media and email. Some are about organization, such as calendars and note taking. Some are simply digital interfaces into a part of the real world that's hard for programmers to navigate, like dating apps. But they all do the same thing. They give users a nice way to interact with data.\n\nData represents the real world. All data describes something _real_. That's what object-oriented programming is all about: it gives us a nice way to model our data after real-world objects. It takes data, which dumb computers like, and adds some abstraction so smart humans can impose our will onto the computers. It makes code easy to read, easy to reason about, and highly reusable.\n\nWhen writing Dart code, you'll likely want to create separate classes for everything that can represent a real-world \"thing.\" _Thing_ is a carefully chosen word, because it's so vague. (This is a great example of something that would make a dumb computer explode but that a smart human can make some sense of.)\n\nConsider if we were writing a point-of-sale (POS) system used to sell goods to customers. What kinds of classes do you think you'd need to represent \"things\" (or data)? What kind of \"things\" does a POS app need to know about? Perhaps we need classes to represent a `Customer`, `Business`, `Employee`, `Product`, and `Money`. Those are all classes that represent real-world things. But it gets a bit hairier from here.\n\nPonder some questions with me:\n\n* We may want a class for `Transaction` and `Sale`. In real life, a transaction is a process or event. Should this be represented with a function or a class?\n* If we're selling bananas, should we use a `Product` class and give it a property that describes what _type_ of product it is? Or should we have a `Banana` class?\n* Should we define a top-level variable or a class that has only a single property? For instance, if we need to write a function that simply adds two numbers together, should we define a `Math` class with an `add` method, or just write the method as a static, global variable?\n\nUltimately, these decisions are up to you, the programmer. There is no single right answer.\n\nMy rule of thumb is, \"When in doubt, make a new class.\" Recall those previous questions: should a transaction be represented by a function of `Business` or its own class? I'd say make it a class. And that brings me all the way back to why I used the vague word _thing_ earlier. A thing isn't just a physical object; it can be an idea, an event, a logical grouping of adjectives, and so on. In this example, I would make a class that looks like this:\n\n```dart\nclass TransactionEvent {\n  // properties and methods\n}\n```\n\nAnd that might be it. It might have no properties and no methods. Creating classes for events makes the type safety of Dart that much more effective.\n\nThe bottom line is that you can (and, I'd argue, should) make a class that represents any \"thing\" that isn't obviously an action you can do or a word you'd use to describe some detail of a \"thing.\" For instance, you (a human) can exchange money with someone. It makes sense to say \"I exchange money.\" It doesn't make sense to say, \"I transaction,\" even though a transaction is an idea. Having a `Transaction` class makes sense, but an `ExchangeMoney` class doesn't.","created_at":"2020-07-18T17:47:22.222Z","id":38,"slug":"intro-to-oop","title":"Intro to OOP","tutorial":5,"updated_at":"2020-07-18T17:47:22.229Z"},{"author":1,"content":"Getters and setters are special methods that provide explicit read and write access to an object's properties. \n\n### Getters\n\nGetters are often useful to set _computed properties_. In other words, instance variables that rely on other, non-constant variables.\n\n```dart\nclass Rectangle {\n  final int width, height;\n  \n  Rectangle(this.width, this.height);\n    \n  // This computed property is treated like a function\n  // that returns a value.\n  int get area => width * height;\n}\n```\n\n### Setters\n\nSetters are similar to getters in that they're syntactic-sugar for methods. But, setters don't provide read-access to a variable. They're used to set the value of a variable and nothing else.\n\nThese are often useful when you want to execute some code in response to a variable being assigned a value, or when a properties value needs to be computed when set.\n\n```run-dartpad:theme-light:run-false:split-60\nclass Rectangle {\n  final int width, height;\n  \n  Rectangle(this.width, this.height);\n    \n  int get area => width * height;\n\n   // Use a private variable to \n   // expose the value with a getter; \n   Point _center;\n   Point get center => _center;\n   set center(Point origin) {\n     _center = Point(\n       origin.x + width / 2,\n       origin.y + height / 2,\n     );\n   } \n}\n\nvoid main() {\n  var rectangle = Rectangle(12,6);\n  print(rectangle.area);\n  // The setter will calculate the center based on what we tell it is the\n  // _origin_ (top left corner) of the rectangle on a plot.\n  // in this case, we're setting the origin at (4,4). \n  rectangle.center = Point(4,4);  \n  print(rectangle.cernter);\n}\n```","created_at":"2020-07-18T21:07:33.215Z","id":43,"slug":"getters-and-setters","title":"Getters and setters","tutorial":5,"updated_at":"2020-07-18T21:07:33.224Z"},{"author":1,"content":"You can _inherit from_ or _extend_ a class using the `extends` keyword. This allows you share properties and methods between classes that are similar, but not exactly the same. Also, it allows different _subtypes_ to share a common runtime type so that static analysis doesn't fail. (More on this below);\n\nThe classic example is using different types of animals.\n\n```run-dartpad:theme-light:run-false:split-60\nclass Animal {\n  Animal(this.name, this.age);\n  \n  int age;\n  String name;\n\n  void talk() {\n    print('grrrr');\n  }\n}\n\nclass Cat extends Animal {\n  // use the 'super' keyword to interact with \n  // the super class of Cat\n  Cat(String name, int age) : super(name, age);\n  \n  void talk() {\n    print('meow');\n  }\n  \n}\n\n\nclass Dog extends Animal {\n  // use the 'super' keyword to interact with \n  // the super class of Cat\n  Dog(String name, int age) : super(name, age);\n  \n  void talk() {\n    print('bark');\n  }\n  \n}\n\nvoid main() {\n  var cat = Cat(\"Phoebe\",1);\n  var dog = Dog(\"Cowboy\", 2);\n  \n  dog.talk();\n  cat.talk();\n}\n```\n\nHere, the Dog and Cat classes share the common properties of Animal, reducing the need to duplicate code in each class. But, it wouldn't make much sense if they both said \"meow\" when you called `talk`. So, talk is defined separately on the different classes, and is implemented correctly on each animal.\n\n### Some 'gotchas' with inheritance\n\nAs you'll see, inheritance is not without it's problems. What if you decided to change that 'talk' method to 'makeNoise'?\n \nYou now have to update the code for both the Cat and Dog API. If you didn't, then anywhere you call `Animal.talk` may fail. For instance, if you have code that doesn't care what _subtype_ of animal it gets, it just knows it needs to make that animal talk. \n\nThat's an example of the statement I made earlier about subtypes sharing super types. An object of type `Cat` _also_ is of type `Animal`. Therefor, Cat instances can be passed into functions that require `Animal` instances.\n\n```dart\nrecordAnimalNoise(Animal animal) {\n  _recordNoise(animal.talk());\n}\n\nmain() {\n  recordAnimalNoise(Cat('Wallace', 1)); // OK!\n  recordAnimalNoise(Dog('Lizard', 3)); // OK!\n}\n```\n\nThis problem can be solved using other features of Dart's classes, which are discussed in the next few examples.","created_at":"2020-07-18T21:08:21.225Z","id":44,"slug":"extending-classes-inheritance","title":"Extending classes (inheritance)","tutorial":5,"updated_at":"2020-07-18T21:08:21.231Z"},{"author":1,"content":"Mixins are a way of reusing a class’s code in different class hierarchies. For example, you might have a class called `Employee` which has methods like `clockIn`. The code in those classes may be useful for both `Bartender` and `Nurse`. But, now imagine you're introducing a class called `Doctor`. You probably have some functionality on `Nurse` (such as a method called `takeTemperature`) that you'd like on `Doctor`, but not that you want to add to `Employee`. This is a great place to use a `mixin` called `Medical`.\n\n```dart\nclass Employee {\n  void clockIn() {...}\n}\n\nmixin Medical {\n   int takeTemperature {...}\n}\n\n\n\n// use mixins on your classes via the `with` keyword\nclass Nurse extends Employee with Medical {}\nclass Doctor extends Employee with Medical {\n  performSurgery() {...}  \n}\nclass Bartender extends Employee {}\n```\n\nWith this architecture, your bartender can 'clock in', but cannot 'takeTemperature'. Both Nurse and Doctor can do both, and the doctor can performSurgery. ","created_at":"2020-07-19T18:58:42.361Z","id":49,"slug":"mixins","title":"Mixins","tutorial":5,"updated_at":"2020-07-19T18:58:42.366Z"},{"author":1,"content":"An _abstract class_, which is similar to an _interface_, defines a class that cannot be instantiated. \n\nAbstract classes keep your code honest and type safe. It ensures that all _implementation subclasses_ define all the properties and methods that abstract class defines, but leaves the implementation to each subclass. \n\n```run-dartpad:theme-light:run-false:split-60\nabstract class Animal {\n  int age;\n  String name;\n\n  // no method body means you're defining an abstract method\n  // abstract methods must be overridden in implementation classes\n  void talk();\n\n  // abstract classes _can_ implement some functionality. \n  // when the method functionality is written on the abstract class,\n  // the implementation subclasses don't have to override it.\n  void growl() => print('grrrrr');\n}\n\nclass Cat implements Animal {\n  @override\n  int age;\n\n  @override\n  String name;\n\n  Cat(this.name, this.age);\n\n  @override\n  void talk() {\n    print('meow');\n  }\n}\n\nclass Dog implements Animal {\n  @override\n  int age;\n\n  @override\n  String name;\n\n  Dog(String name, int age);\n\n  @override\n  void talk() {\n    print('bark');\n  }\n}\n\n// This method expects an Animal instance as an argument\n// But, Animal is _abstract_, which means you cannot instantiate it directly\n// So, any class that _implements_ Animal is guaranteed to have\n// overriden the methods and properties on the Animal interface, \n// which makes it 'type safe'.\nvoid makeAnimalNoise(Animal animal) => animal.talk();\n\nmain() {\n  final cat = Cat('Nora', 5);\n  final dog = Dog('Pepperstake', 1);\n  makeAnimalNoise(cat);\n  makeAnimalNoise(dog);\n\n  dog.growl();\n  cat.growl();\n}\n```\n","created_at":"2020-07-19T18:58:19.129Z","id":48,"slug":"abstract-classes-and-interfaces","title":"Abstract classes (and interfaces)","tutorial":5,"updated_at":"2020-07-19T18:58:19.139Z"},{"author":1,"content":"You have several options when defining methods on classes. First, let's look at basic examples of each.\n\n```dart\nclass Microwave {\n  // basic method  \n  void startCooking (){}\n\n  // private method\n  // this cannot be called from outside the class itself\n  // it is not exposed to _instances_ of the class\n  void _startTimer() {}\n  \n  // a static method isn't tied to an instance\n  // rather, it's logically tied to a class. \n  // static methods are compile-time constant, \n  // so you don't have access to 'this'\n  static bool compareWatts(Microwave a, Microwave b) {\n    if (a.power > b.power) return -1;\n    if (b.power > a.power) return 1;\n        \n    // else they're the same\n    return 0;\n  }\n}\n```\n\n```run-dartpad:theme-light:run-false:split-60\nclass Microwave {\n  final int power;\n\n  Microwave(this.power);\n\n  void startCooking() {\n    _startTimer();\n    print('starting cooking!')\n  }\n\n  void _startTimer() {\n    print('starting timer!');\n  }\n  \n  static int compareWatts(Microwave a, Microwave b) {\n    if (a.power > b.power) return -1;\n    if (b.power > a.power) return 1;\n    \n    // else they're the same\n    return 0;\n  }\n}\n\nvoid main() {\n  var averageMicrowave = Microwave(1100);\n  var miniMicrowave = Microwave(800);\n  var superMicrowave = Microwave(1500);\n\n  // calling a basic instance method\n  averageMicrowave.startCooking();\n\n  // calling a static method\n  // which you must call on the class, rather than the instance\n  print(Microwave.compareWatts(averageMicrowave, superMicrowave));\n}\n```","created_at":"2020-07-18T21:06:29.801Z","id":42,"slug":"methods-static-private-etc","title":"Methods: static, private, etc","tutorial":5,"updated_at":"2020-07-19T18:56:15.677Z"},{"author":1,"content":"Extension methods are new as of Dart 2.7. They allow you to add functionality to existing libraries and classes. For example, you can add extra functionality to the Dart core `String` library, that are only available in your app. \n\n```run-dartpad:theme-light:run-false:split-60\nextension on DateTime {\n  String get humanize {\n    // you have access to the instance in extension methods via 'this' keyword. \n    return \"${this.day}/${this.month}/${this.year}\";\n  }\n}\n\nvoid main() {\n  final dateTime = DateTime.now();\n  print(dateTime.humanize);\n}\n```  ","created_at":"2020-07-19T18:59:12.861Z","id":50,"slug":"extension-methods","title":"Extension methods","tutorial":5,"updated_at":"2020-07-19T18:59:12.868Z"}]},"strapiTableOfContents":{"contents":"{\n  \"Dart\": {\n    \"Getting Started with Dart\": [\n      \"About Dart\",\n      \"Install Dart on your machine\",\n      \"Dartpad\",\n      \"Text Editors: Intellij and VSCode\",\n      \"Resources: Documentation and Pub.dev\",\n      \"Hello World\",\n      \"The main function\",\n      \"Print to the console\"\n    ],\n    \"Dart Fundamentals\": [\n      \"Values and variables\",\n      \"Comments\",\n      \"const and final variables\",\n      \"Arithmetic and Comparison Operators\",\n      \"Assignment Operators\",\n      \"Logical Operators\",\n      \"Null Aware Operators\",\n      \"Type Test Operators\",\n      \"Bitwise and Shift Operators\",\n      \"Control Flow: if, else, else if\",\n      \"Switch statements and case\",\n      \"Ternary Conditional operator\",\n      \"Loops: for and while\",\n      \"Anatomy of Dart Functions\",\n      \"Arrow functions\",\n      \"Function arguments: default, optional, named\",\n      \"Lexical Scope\",\n      \"Cascade notation\"\n    ],\n    \"Data Types\": [\n      \"Intro to Dart's Type System\",\n      \"Numbers\",\n      \"Strings\",\n      \"Booleans\",\n      \"dynamic\",\n      \"lists\",\n      \"sets\",\n      \"maps\"\n    ],\n    \"Object-Oriented Programming\": [\n      \"Intro to OOP\",\n      \"Classes\",\n      \"Constructors\",\n      \"Properties and methods\",\n      \"Methods: static, private, etc\",\n      \"Getters and setters\",\n      \"Extending classes (inheritance)\",\n      \"Initializer lists and final properties\",\n      \"Factory methods\",\n      \"Singletons\",\n      \"Abstract classes (and interfaces)\",\n      \"Mixins\",\n      \"Extension methods\"\n    ],\n    \"Iterables, Iterators, and Collections\": [\n      \"What are collections (and iterables)?\",\n      \"Looping: for-in and forEach\",\n      \"Reading elements pt 1: first, last\",\n      \"Adding elements: add and insert (all)\",\n      \"Checking for elements: contains, indexOf, any, every\",\n      \"Removing elements: remove, clear, removeWhere\",\n      \"Filtering elements: where, takeWhile, and skipWhile\",\n      \"Changing elements: map and expand\",\n      \"Deriving values from elements: fold, reduce, join\",\n      \"Type casting collections: cast, as, retype, toSet, toList\",\n      \"Iterators: understanding and creating your own\",\n      \"Iterable-like methods on maps (and putIfAbsent)\"\n    ]\n  },\n  \"Flutter\": {\n    \"Getting started with Flutter\": [\n      \"About Flutter\",\n      \"IDEs and resources\"\n    ],\n    \"Widgets\": [\n      \"Intro to Widgets\",\n      \"Widget types: Stateful and Stateless\",\n      \"StatefulWidget lifecycle\",\n      \"The Widget tree\",\n      \"BuildContext\",\n      \"Inherited Widgets\",\n      \"Thinking in widgets\"\n    ],\n    \"Intro Flutter App\": [\n      \"Intro and Setup\",\n      \"Data Model and HTTP\",\n      \"Build a custom widget\",\n      \"ListView and builder pattern\",\n      \"Gradient Backgrounds\",\n      \"Routing: Add a detail page\",\n      \"Routing 2: Add a form page\",\n      \"User Input\",\n      \"Sliders and Buttons\",\n      \"Snackbars and Dialogs\",\n      \"Built-in Animation: AnimatedCrossFade\",\n      \"Built-in Animation: Hero transition\"\n    ],\n    \"Custom Animation: Progress Indicator\": [\n      \"Intro and Overview\",\n      \"Build the example app boiler-plate\",\n      \"Custom Widget: Peg\",\n      \"Tween and AnimationController classes\",\n      \"Tween by example\",\n      \"Using Tweens and Intervals\",\n      \"Wrap the Pegs in AnimatedWidgets\",\n      \"Bring it all together\"\n    ],\n    \"State Management: Blocs without Libraries\": [\n      \"What are blocs?\",\n      \"Calendar App introduction\",\n      \"Create bloc one\",\n      \"Create a bloc provider\",\n      \"Using StreamBuilders with blocs\",\n      \"Create bloc two: Add/Edit Tasks\",\n      \"Consume the second bloc's streams\",\n      \"Complete source code\"\n    ],\n    \"State Management: Provider\": [\n      \"What is Provider?\",\n      \"The most basic example using Provider\",\n      \"ChangeNotifierProvider\",\n      \"Rebuilding widgets with Consumer\",\n      \"Finer build control with Selector\",\n      \"Future Provider\",\n      \"MultiProvider micro lesson\",\n      \"Stream Provider\",\n      \"Using context extensions for more control\",\n      \"ProxyProvider\",\n      \"Using .value constructors\",\n      \"The final example (A shopping cart app)\",\n      \"For the curious: How is provider implemented\"\n    ],\n    \"Handling Data with Brick: Offline First with Rest\": [\n      \"About Brick and setup\",\n      \"Adding a Repository\",\n      \"Adding a Model\",\n      \"Generating Code\",\n      \"Rendering Models\",\n      \"Adding an Association\"\n    ]\n  }\n}"}},"pageContext":{"slug":"extending-classes-inheritance","tutorialTitle":"Object-Oriented Programming","previous":{"author":1,"content":"Getters and setters are special methods that provide explicit read and write access to an object's properties. \n\n### Getters\n\nGetters are often useful to set _computed properties_. In other words, instance variables that rely on other, non-constant variables.\n\n```dart\nclass Rectangle {\n  final int width, height;\n  \n  Rectangle(this.width, this.height);\n    \n  // This computed property is treated like a function\n  // that returns a value.\n  int get area => width * height;\n}\n```\n\n### Setters\n\nSetters are similar to getters in that they're syntactic-sugar for methods. But, setters don't provide read-access to a variable. They're used to set the value of a variable and nothing else.\n\nThese are often useful when you want to execute some code in response to a variable being assigned a value, or when a properties value needs to be computed when set.\n\n```run-dartpad:theme-light:run-false:split-60\nclass Rectangle {\n  final int width, height;\n  \n  Rectangle(this.width, this.height);\n    \n  int get area => width * height;\n\n   // Use a private variable to \n   // expose the value with a getter; \n   Point _center;\n   Point get center => _center;\n   set center(Point origin) {\n     _center = Point(\n       origin.x + width / 2,\n       origin.y + height / 2,\n     );\n   } \n}\n\nvoid main() {\n  var rectangle = Rectangle(12,6);\n  print(rectangle.area);\n  // The setter will calculate the center based on what we tell it is the\n  // _origin_ (top left corner) of the rectangle on a plot.\n  // in this case, we're setting the origin at (4,4). \n  rectangle.center = Point(4,4);  \n  print(rectangle.cernter);\n}\n```","created_at":"2020-07-18T21:07:33.215Z","id":43,"slug":"getters-and-setters","title":"Getters and setters","tutorial":5,"updated_at":"2020-07-18T21:07:33.224Z"},"next":{"author":1,"content":"Mixins are a way of reusing a class’s code in different class hierarchies. For example, you might have a class called `Employee` which has methods like `clockIn`. The code in those classes may be useful for both `Bartender` and `Nurse`. But, now imagine you're introducing a class called `Doctor`. You probably have some functionality on `Nurse` (such as a method called `takeTemperature`) that you'd like on `Doctor`, but not that you want to add to `Employee`. This is a great place to use a `mixin` called `Medical`.\n\n```dart\nclass Employee {\n  void clockIn() {...}\n}\n\nmixin Medical {\n   int takeTemperature {...}\n}\n\n\n\n// use mixins on your classes via the `with` keyword\nclass Nurse extends Employee with Medical {}\nclass Doctor extends Employee with Medical {\n  performSurgery() {...}  \n}\nclass Bartender extends Employee {}\n```\n\nWith this architecture, your bartender can 'clock in', but cannot 'takeTemperature'. Both Nurse and Doctor can do both, and the doctor can performSurgery. ","created_at":"2020-07-19T18:58:42.361Z","id":49,"slug":"mixins","title":"Mixins","tutorial":5,"updated_at":"2020-07-19T18:58:42.366Z"}}},"staticQueryHashes":["2185715291","3564968493","63159454"]}