{"id":15008451,"url":"https://github.com/mohammadkarbalaee/oop-dart","last_synced_at":"2025-04-09T16:04:53.590Z","repository":{"id":214466374,"uuid":"736597085","full_name":"mohammadkarbalaee/oop-dart","owner":"mohammadkarbalaee","description":"Object-oriented programming concepts in Dart","archived":false,"fork":false,"pushed_at":"2023-12-30T18:09:27.000Z","size":36,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T16:04:47.276Z","etag":null,"topics":["dart","dartlang","flutter","object-oriented-programming","oop","sbu","shahid-beheshti-university"],"latest_commit_sha":null,"homepage":"https://t.me/flutter_sbu","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mohammadkarbalaee.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-28T10:37:48.000Z","updated_at":"2025-03-04T21:51:57.000Z","dependencies_parsed_at":"2023-12-28T11:46:03.618Z","dependency_job_id":"c7f6dd0f-50d0-453e-b015-aed3356094fe","html_url":"https://github.com/mohammadkarbalaee/oop-dart","commit_stats":null,"previous_names":["mohammadkarbalaee/advanced-dart"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mohammadkarbalaee%2Foop-dart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mohammadkarbalaee%2Foop-dart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mohammadkarbalaee%2Foop-dart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mohammadkarbalaee%2Foop-dart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mohammadkarbalaee","download_url":"https://codeload.github.com/mohammadkarbalaee/oop-dart/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065289,"owners_count":21041871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","dartlang","flutter","object-oriented-programming","oop","sbu","shahid-beheshti-university"],"created_at":"2024-09-24T19:18:48.652Z","updated_at":"2025-04-09T16:04:53.571Z","avatar_url":"https://github.com/mohammadkarbalaee.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Object-Oriented Programming (OOP) in Dart\n\nObject-oriented programming (OOP) is a programming paradigm that structures code using objects, which are instances of classes. Dart fully supports OOP principles, and this section provides a comprehensive exploration of key OOP concepts in Dart.\n\n## Classes and Objects\n\nIn Dart, a class is a blueprint for creating objects. Objects are instances of classes and encapsulate data and behavior. Let's expand on the basic example:\n\n```dart\nclass Animal {\n  String name;\n  int age;\n\n  Animal(this.name, this.age);\n\n  void makeSound() {\n    print('Animal makes a sound');\n  }\n}\n\nclass Dog extends Animal {\n  String breed;\n\n  Dog(String name, int age, this.breed) : super(name, age);\n\n  @override\n  void makeSound() {\n    print('Dog barks');\n  }\n\n  void showDetails() {\n    print('Name: $name, Age: $age, Breed: $breed');\n  }\n}\n\nvoid main() {\n  // Creating an instance of the Dog class\n  var myDog = Dog('Buddy', 3, 'Golden Retriever');\n\n  // Accessing properties\n  print('Name: ${myDog.name}, Age: ${myDog.age}, Breed: ${myDog.breed}');\n\n  // Invoking methods\n  myDog.makeSound();\n  myDog.showDetails();\n}\n```\n\nIn this example, we have an `Animal` class with properties `name` and `age` and a method `makeSound`. The `Dog` class extends `Animal` and introduces an additional property `breed` and a method `showDetails`.\n\n## Constructors\n\nConstructors are special methods used for initializing objects. Dart supports both default and named constructors. Let's extend the previous example to include named constructors:\n\n```dart\nclass Animal {\n  String name;\n  int age;\n\n  Animal(this.name, this.age);\n\n  Animal.namedConstructor(this.name) : age = 0;\n\n  void makeSound() {\n    print('Animal makes a sound');\n  }\n}\n\nclass Dog extends Animal {\n  String breed;\n\n  Dog(String name, int age, this.breed) : super(name, age);\n\n  Dog.namedConstructor(String name, String breed)\n      : breed = breed,\n        super.namedConstructor(name);\n\n  @override\n  void makeSound() {\n    print('Dog barks');\n  }\n\n  void showDetails() {\n    print('Name: $name, Age: $age, Breed: $breed');\n  }\n}\n\nvoid main() {\n  var myDog = Dog('Buddy', 3, 'Golden Retriever');\n\n  var anotherDog = Dog.namedConstructor('Max', 'Labrador');\n\n  myDog.showDetails();\n  anotherDog.showDetails();\n}\n```\n\nHere, we've added named constructors `namedConstructor` to both the `Animal` and `Dog` classes. This allows for alternative ways to construct objects.\n\n## Inheritance\n\nInheritance is a fundamental OOP concept that allows a class to inherit properties and methods from another class. The `extends` keyword in Dart is used to implement inheritance. Let's extend our example further:\n\n```dart\nclass Animal {\n  String name;\n  int age;\n\n  Animal(this.name, this.age);\n\n  Animal.namedConstructor(this.name) : age = 0;\n\n  void makeSound() {\n    print('Animal makes a sound');\n  }\n}\n\nclass Dog extends Animal {\n  String breed;\n\n  Dog(String name, int age, this.breed) : super(name, age);\n\n  Dog.namedConstructor(String name, String breed)\n      : breed = breed,\n        super.namedConstructor(name);\n\n  @override\n  void makeSound() {\n    print('Dog barks');\n  }\n\n  void showDetails() {\n    print('Name: $name, Age: $age, Breed: $breed');\n  }\n}\n\nclass Cat extends Animal {\n  bool hasStripes;\n\n  Cat(String name, int age, this.hasStripes) : super(name, age);\n\n  void makeSound() {\n    print('Cat meows');\n  }\n\n  void showDetails() {\n    print('Name: $name, Age: $age, Has Stripes: $hasStripes');\n  }\n}\n\nvoid main() {\n  var myDog = Dog('Buddy', 3, 'Golden Retriever');\n  var myCat = Cat('Whiskers', 2, true);\n\n  myDog.showDetails();\n  myCat.showDetails();\n}\n```\n\nIn this extension, we've introduced a new class `Cat` that also extends `Animal`. The `Cat` class has its own properties and methods, and it overrides the `makeSound` method inherited from `Animal`.\n\n## Encapsulation\n\nEncapsulation is the concept of bundling data and methods that operate on that data within a single unit, i.e., a class. Dart supports encapsulation through the use of access modifiers (`public`, `private`, and `protected`). Dart uses an underscore `_` as a convention for marking private members. Let's modify our example to incorporate encapsulation:\n\n```dart\nclass Animal {\n  String _name; // Private property\n \n\n int _age; // Private property\n\n  Animal(this._name, this._age);\n\n  Animal.namedConstructor(this._name) : _age = 0;\n\n  void makeSound() {\n    print('Animal makes a sound');\n  }\n\n  // Getter for private property _name\n  String get name =\u003e _name;\n\n  // Setter for private property _name\n  set name(String value) =\u003e _name = value;\n\n  // Getter for private property _age\n  int get age =\u003e _age;\n\n  // Setter for private property _age\n  set age(int value) =\u003e _age = value;\n}\n\nclass Dog extends Animal {\n  String _breed; // Private property\n\n  Dog(String name, int age, this._breed) : super(name, age);\n\n  Dog.namedConstructor(String name, String breed)\n      : _breed = breed,\n        super.namedConstructor(name);\n\n  @override\n  void makeSound() {\n    print('Dog barks');\n  }\n\n  void showDetails() {\n    print('Name: $name, Age: $age, Breed: $_breed');\n  }\n}\n\nvoid main() {\n  var myDog = Dog('Buddy', 3, 'Golden Retriever');\n  \n  // Accessing private properties through getters\n  print('Name: ${myDog.name}, Age: ${myDog.age}, Breed: ${myDog.showDetails()}');\n}\n```\n\nIn this example, properties `_name`, `_age`, and `_breed` are marked as private using the underscore `_`. Getters and setters are then used to provide controlled access to these private properties.\n\n## Abstraction\n\nAbstraction involves hiding complex implementation details and showing only the necessary features of an object. Dart achieves abstraction through abstract classes and methods. Let's create an abstract class and extend it:\n\n```dart\nabstract class Shape {\n  // Abstract method\n  void draw();\n\n  // Regular method\n  void getInfo() {\n    print('This is a shape.');\n  }\n}\n\nclass Circle extends Shape {\n  double radius;\n\n  Circle(this.radius);\n\n  @override\n  void draw() {\n    print('Drawing a circle with radius $radius');\n  }\n}\n\nclass Square extends Shape {\n  double side;\n\n  Square(this.side);\n\n  @override\n  void draw() {\n    print('Drawing a square with side $side');\n  }\n}\n\nvoid main() {\n  var myCircle = Circle(5.0);\n  var mySquare = Square(4.0);\n\n  myCircle.draw();\n  myCircle.getInfo();\n\n  mySquare.draw();\n  mySquare.getInfo();\n}\n```\n\nHere, `Shape` is an abstract class with an abstract method `draw()`. The `Circle` and `Square` classes extend `Shape` and provide their own implementations of the `draw()` method.\n\n## Polymorphism\n\nPolymorphism allows objects of different types to be treated as objects of a common type. Dart supports polymorphism through method overriding. Let's demonstrate polymorphism using our existing classes:\n\n```dart\nvoid main() {\n  Shape myCircle = Circle(5.0);\n  Shape mySquare = Square(4.0);\n\n  drawShape(myCircle);\n  drawShape(mySquare);\n}\n\nvoid drawShape(Shape shape) {\n  shape.draw();\n}\n```\n\nIn this example, `myCircle` and `mySquare` are both treated as `Shape` objects when passed to the `drawShape` function. The `draw()` method of the appropriate class (either `Circle` or `Square`) is called based on the actual type of the object.\n\n## Conclusion\n\nThis comprehensive exploration covers the fundamental concepts of Object-Oriented Programming (OOP) in Dart. Understanding these concepts, including classes, inheritance, constructors, encapsulation, abstraction, and polymorphism, is crucial for writing efficient and maintainable Dart code. For more in-depth information and advanced use cases, refer to the official Dart documentation: [Dart Documentation](https://dart.dev/guides).\n\n---\n\n# Extensions in Dart\n\nDart introduced extensions as a feature that allows adding new functionality to existing classes without modifying their source code. This provides a way to extend the behavior of types you don't own or cannot modify. Let's explore the concept of extensions in Dart and how to implement them.\n\n## Extension Declaration\n\nTo declare an extension, you use the `extension` keyword followed by a name and the `on` keyword specifying the type you want to extend. Inside the extension, you can define new methods, getters, setters, and fields:\n\n```dart\nextension StringExtension on String {\n  int parseInt() {\n    return int.parse(this);\n  }\n\n  String capitalize() {\n    return this.isNotEmpty ? this[0].toUpperCase() + this.substring(1) : this;\n  }\n}\n```\n\nIn this example, we declare an extension named `StringExtension` that extends the `String` class. It provides two new methods: `parseInt` to parse a string into an integer and `capitalize` to capitalize the first letter of the string.\n\n## Using Extensions\n\nOnce an extension is declared, you can use its methods as if they were defined directly on the extended type. Here's how you use the `StringExtension` extension:\n\n```dart\nvoid main() {\n  String numberString = '42';\n  int number = numberString.parseInt();\n\n  print('Parsed number: $number');\n\n  String greeting = 'hello';\n  String capitalizedGreeting = greeting.capitalize();\n\n  print('Capitalized greeting: $capitalizedGreeting');\n}\n```\n\nIn this example, the `parseInt` method from the `StringExtension` extension is used to parse a string into an integer, and the `capitalize` method is used to capitalize the first letter of a string.\n\n## Limitations\n\n- Extensions can only be declared on non-nullable types.\n- They cannot access private members of the extended type.\n- Extensions are not inherited, meaning if a subclass extends a class, it won't automatically inherit the extensions of the superclass.\n\n## Advanced Usage\n\nExtensions can be used to add functionality to third-party or system libraries without modifying their source code. For example, you could create an extension to add extra methods to the `List` class:\n\n```dart\nextension ListExtension\u003cE\u003e on List\u003cE\u003e {\n  E safeGet(int index) {\n    return (index \u003e= 0 \u0026\u0026 index \u003c this.length) ? this[index] : null;\n  }\n\n  void printAll() {\n    this.forEach(print);\n  }\n}\n```\n\nNow, you can use these methods on any list:\n\n```dart\nvoid main() {\n  List\u003cint\u003e numbers = [1, 2, 3, 4, 5];\n\n  int element = numbers.safeGet(2);\n  print('Element at index 2: $element');\n\n  numbers.printAll();\n}\n```\n\nThis is a powerful feature for enhancing existing types and promoting code reuse.\n\n## Conclusion\n\nExtensions in Dart provide a clean and efficient way to add new functionality to existing types. They improve code readability and maintainability by allowing you to extend classes without modifying their source code. When used carefully, extensions can be a valuable tool for writing concise and expressive Dart code. For more in-depth information and advanced use cases, refer to the official Dart documentation on [extensions](https://dart.dev/guides/language/extension-methods).\n\n---\n\n# Mixins\n\nMixins in Dart are a way to reuse a class's code in multiple class hierarchies. They allow you to extend the functionality of a class without using traditional inheritance. Mixins are a powerful feature in Dart that promotes code reuse and separation of concerns. Here's a step-by-step guide to understanding and using mixins in Dart:\n\n### 1. **Define a Mixin:**\n\nCreate a mixin by using the `mixin` keyword followed by a name. A mixin can include methods, properties, and even other mixins.\n\n```dart\nmixin LoggingMixin {\n  void log(String message) {\n    print('Log: $message');\n  }\n}\n```\n\nIn this example, `LoggingMixin` defines a simple `log` method.\n\n### 2. **Use Mixin in a Class:**\n\nTo use a mixin in a class, use the `with` keyword followed by the mixin's name.\n\n```dart\nclass Calculator with LoggingMixin {\n  int add(int a, int b) {\n    log('Adding $a and $b');\n    return a + b;\n  }\n}\n```\n\nNow, the `Calculator` class can use the `log` method from the `LoggingMixin`.\n\n### 3. **Instantiate and Use the Class:**\n\nCreate an instance of the class and use its methods as usual.\n\n```dart\nvoid main() {\n  var calculator = Calculator();\n  var result = calculator.add(3, 7);\n  print('Result: $result');\n}\n```\n\nThe `Calculator` class now benefits from the `log` method provided by the `LoggingMixin`.\n\n### 4. **Multiple Mixins:**\n\nYou can use multiple mixins in a single class by separating them with commas.\n\n```dart\nmixin MathOperations {\n  int multiply(int a, int b) =\u003e a * b;\n}\n\nclass AdvancedCalculator with LoggingMixin, MathOperations {\n  //...\n}\n```\n\nNow, `AdvancedCalculator` has access to both the `log` method from `LoggingMixin` and the `multiply` method from `MathOperations`.\n\n### 5. **Order of Mixins:**\n\nThe order in which mixins are applied matters. The behavior of the class may vary based on the order of mixins. If two mixins provide the same method or property, the one declared first takes precedence.\n\n### 6. **Understanding `on` Clause (Optional):**\n\nYou can use the `on` clause to restrict the types that can use the mixin. This ensures that the mixin is applied only to specific types.\n\n```dart\nmixin LoggingMixin on Calculator {\n  //...\n}\n```\n\nIn this example, `LoggingMixin` can only be used with classes that extend or implement `Calculator`.\n\n### 7. **Considerations:**\n\n- Mixins promote code reuse and maintainability.\n- They allow you to avoid the diamond problem (ambiguity that arises when a class inherits from two classes that have a common ancestor).\n- Be mindful of the order of mixins and potential conflicts.\n\n### Example Code:\n\nHere's a complete example incorporating all the concepts:\n\n```dart\nmixin LoggingMixin {\n  void log(String message) {\n    print('Log: $message');\n  }\n}\n\nmixin MathOperations {\n  int multiply(int a, int b) =\u003e a * b;\n}\n\nclass Calculator with LoggingMixin, MathOperations {\n  int add(int a, int b) {\n    log('Adding $a and $b');\n    return a + b;\n  }\n}\n\nvoid main() {\n  var advancedCalculator = Calculator();\n  var result = advancedCalculator.add(3, 7);\n  print('Result: $result');\n\n  var multiplicationResult = advancedCalculator.multiply(4, 5);\n  print('Multiplication Result: $multiplicationResult');\n}\n```\n\nThis example demonstrates a `Calculator` class using both `LoggingMixin` and `MathOperations` mixins.\n\nBy understanding and using mixins effectively, you can enhance the modularity and flexibility of your Dart code.\n\n---\n\n# Enums\n\nEnums in Dart allow you to define a set of named constant values. They are often used to represent a fixed set of values or options. Here's an example of how you can use enums in Dart:\n\n```dart\n// Define an enum named 'Status'\nenum Status {\n  idle,\n  running,\n  paused,\n  stopped,\n}\n\nvoid main() {\n  // Using enum values\n  Status currentStatus = Status.running;\n\n  // Switch statement with enum\n  switch (currentStatus) {\n    case Status.idle:\n      print(\"The system is idle.\");\n      break;\n    case Status.running:\n      print(\"The system is running.\");\n      break;\n    case Status.paused:\n      print(\"The system is paused.\");\n      break;\n    case Status.stopped:\n      print(\"The system is stopped.\");\n      break;\n    default:\n      print(\"Unknown status\");\n  }\n}\n```\n\nIn this example, we define an enum called `Status` with four possible values: `idle`, `running`, `paused`, and `stopped`. We then declare a variable `currentStatus` and assign it the value `Status.running`. Finally, we use a switch statement to check the current status and print a corresponding message.\n\nEnums in Dart are powerful because they provide a way to represent a fixed set of values in a clear and concise manner, making the code more readable and maintainable.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmohammadkarbalaee%2Foop-dart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmohammadkarbalaee%2Foop-dart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmohammadkarbalaee%2Foop-dart/lists"}