조용한 담장

Dart : Class 본문

Dart

Dart : Class

iosroid 2019. 10. 2. 15:16

Dart Class

Dart language tour

class ClassName {
}

var myClass = ClassName();

Class members

., ?.

var p = Point(2, 2);
p.y = 3;
assert(p.y == 3);
num distance = p.distanceTo(Point(4, 4));
// If p is non-null, set its y value to 4.
p?.y = 4;

Constructor

constructor 를 선언하지 않으면 기본적으로 Default constructor 가 생긴다.

Default constructor 는 클래스 이름과 동일한 이름을 가지고 argument 가 없다.

constructor는 상속되지 않는다.

var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});

var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});

// The this keyword refers to the current instance.
class Point {
  num x, y;

  /*
  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
  */

  // 위의 contructor 와 동일.
  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}

// superclass (Person) 의 constructor 호출
class Employee extends Person {
  // Person 은 default constructor 가 없다면 super.fromJson(data) 를 호출해야 한다.
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}

// Redirecting constructors
class Point {
  num x, y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}

Constant constructor (compile-time constant)

const

class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);

  final num x, y;

  const ImmutablePoint(this.x, this.y);
}

var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // They are the same instance!

// constant constructor 가 constant context 밖에 있거나, const 없이 사용면 non-constant object 를 생성한다.
var a = const ImmutablePoint(1, 1); // Creates a constant
var b = ImmutablePoint(1, 1); // Does NOT create a constant
assert(!identical(a, b)); // NOT the same instance!

// const 를 생략할 수 있다.
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};

Factory constructors

매번 새로운 instance를 생성할 필요가 없는 경우에 사용한다.

class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to
  // the _ in front of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    return _cache.putIfAbsent(
        name, () => Logger._internal(name));
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}

var logger = Logger('UI');
logger.log('Button clicked');

Initializer list

Point.fromJson(Map<String, num> json)
    : x = json['x'],
      y = json['y'] {
  print('In Point.fromJson(): ($x, $y)');
}

Point.withAssert(this.x, this.y) : assert(x >= 0) {
  print('In Point.withAssert(): ($x, $y)');
}

// setting up final fields
class Point {
  final num x;
  final num y;
  final num distanceFromOrigin;

  Point(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

main() {
  var p = new Point(2, 3);
  print(p.distanceFromOrigin);
}

Method

Instance methods

import 'dart:math';

class Point {
  num x, y;

  Point(this.x, this.y);

  // instance method
  num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}

Getters and setters

각각의 instance 변수에 getter와 setter가 기본으로 생성된다. 임의로 생성할 수도 있다.

class Rectangle {
  num left, top, width, height;

  Rectangle(this.left, this.top, this.width, this.height);

  // Define two calculated properties: right and bottom.
  num get right => left + width;
  set right(num value) => left = value - width;
  num get bottom => top + height;
  set bottom(num value) => top = value - height;
}

void main() {
  var rect = Rectangle(3, 4, 20, 15);
  assert(rect.left == 3);
  rect.right = 12;
  assert(rect.left == -8);
}

Abstract classes

abstract

interface를 만드는데 유용한 abstract class 를 정의할 때 사용한다. abstract methods 를 가질 수 있다.

// This class is declared abstract and thus can't be instantiated.
abstract class AbstractContainer {
  // Define constructors, fields, methods...

  void updateChildren(); // Abstract method.
}

Implicit interfaces

class 는 class 자신의 모든 멤버를 포함하는 interface 를 정의하게 된다.

implements 를 사용해 다른 class 의 interface 가 사용하는 API 를 사용할 수 있다.

// A person. The implicit interface contains greet().
class Person {
  // In the interface, but visible only in this library.
  final _name;

  // Not in the interface, since this is a constructor.
  Person(this._name);

  // In the interface.
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// An implementation of the Person interface.
class Impostor implements Person {
  get _name => '';

  String greet(String who) => 'Hi $who. Do you know who I am?';
}

String greetBob(Person person) => person.greet('Bob');

void main() {
  print(greetBob(Person('Kathy')));
  print(greetBob(Impostor()));
}

// output:
// Hello, Bob. I am Kathy.
// Hi Bob. Do you know who I am?

// example of a class implements multiple interfaces
class Point implements Comparable, Location {...}

Extending a class

extends subclass 생성할 때 사용.

super superclass 를 참조할 때 사용.

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}

Overriding members

@override

class SmartTelevision extends Television {
  @override
  void turnOn() {...}
  // ···
}

Overridable operators

operator operator operator operator
< + ` `
> / ^ []=
<= ~/ & ~
>= * << ==
% >>  
class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);

  // Operator == and hashCode not shown. For details, see note below.
  // ···
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}

Extending a class.

noSuchMethod()

noSuchMethod() 존재하지 않는 method 나 variable 을 접근하게 되는 경우에 대한 처리를 할 수 있다.

class A {
  // Unless you override noSuchMethod, using a
  // non-existent member results in a NoSuchMethodError.
  @override
  void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: ' +
        '${invocation.memberName}');
  }
}

Enumerated types

Using enums

enum Color { red, green, blue }

assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);

// To get a list of all of the values in the enum, use the enum’s values constant.
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);

var aColor = Color.blue;

switch (aColor) {
  case Color.red:
    print('Red as roses!');
    break;
  case Color.green:
    print('Green as grass!');
    break;
  default: // Without this, you see a WARNING.
    print(aColor); // 'Color.blue'
}

Adding features to a class: mixins

Mixins 은 여러개의 class 를 상속하는 구조에서 특정 class의 코드를 재사용 하기 위한 방법이다.

사용은 with 뒤에 한개 이상의 mixin 의 이름을 추가하여 사용한다.

// use mixin Musical, Aggressive, Demented
class Maestro extends Person with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    canConduct = true;
  }
}

mixin 을 사용하며, constructor 가 없는 class extends Object 구조와 같다.

mixin Musical {
  bool canConduct = false;

  void entertainMe() {
    if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}

on 을 사용하여 특정 타입만 사용할 수 있도록 지정할 수 있다.

mixin MusicalPerformer on Musician {
  // ···
}

Class variables and methods

Static variables

Static variable 은 사용되기 전까지 초기화 되지 않는다.

class Queue {
  static const initialCapacity = 16;
  // ···
}

void main() {
  assert(Queue.initialCapacity == 16);
}

Static methods

instance 에서 호출할 수 없다. 따라서 this가 존재하지 않는다.

class Stranger {
  static void greeting() {
    print('hello');
  }
}

void main() {
  var a = Stranger();
  Stranger.greeting();
  a.greeting(); // ERROR : Static method 'greeting' can't be accessed through an instance.
}

static method 는 compile-time constant 로써 사용이 가능하다. 예를 들어 constant constructor 의 parameter 로 넘길수도 있다.

class Stranger {
  static void greeting(String who) {
    print('$who said hello');
  }
}

class Me {
  final x;

  const Me(this.x);
  void who() {
    x('I');
  }
}

void main() {
  var a = Me(Stranger.greeting);
  a.who();
  var h = Stranger.greeting;
  h('He');
}

Object's type

runtimeType object 의 타입(Type object) 을 얻는다.

print('The type of a is ${a.runtimeType}');

Instance variables

초기화 되지 않은 변수는 null을 가진다.

class Point {
  num x; // Declare instance variable x, initially null.
  num y; // Declare y, initially null.
  num z = 0; // Declare z, initially 0.
}

모든 변수는 getter method 를 가진다.

Non-final(값이 변경 가능한) 변수는 setter method 를 가진다.

Getters and setters.

class Point {
  num x;
  num y;
}

void main() {
  var point = Point();
  point.x = 4; // Use the setter method for x.
  assert(point.x == 4); // Use the getter method for x.
  assert(point.y == null); // Values default to null.
}

Callable classes

함수처럼 호출이 가능한 클래스는 call() method 를 구현하면 된다.

class WannabeFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

main() {
  var wf = new WannabeFunction();
  var out = wf("Hi","there,","gang");
  print('$out');
}

 

'Dart' 카테고리의 다른 글

Dart : print  (0) 2019.11.04
Dart : Asynchronous programming  (0) 2019.10.24
Dart : Exceptions  (0) 2019.09.20
Dart : Control flow statements  (0) 2019.09.17
Dart : Operators  (0) 2019.09.17
Comments