如何使用Dart编程的高级概念

185 阅读12分钟

使用Dart编程的高级概念

编程是一种编写语法的方式,指示计算机按照我们希望的方式执行特定的任务。为了让开发者更好地编程,某些概念如函数声明和使用、条件情况处理、变量声明--赋值--和重新赋值,以及循环都提供了一种实现更好的编程实践的方法。

我们可以把列出的概念归为基本的编程概念,是编程中其他高级概念所需要的基本知识。我们将讨论其中的一些高级概念,这些概念使编程变得更好,使用起来更有趣。

目标

在本教程结束时,读者应该能够。

  • 编写有助于我们理解编程的高级概念的情况代码。
  • 了解编程的高级概念,如类、对象、抽象、多态性、封装、继承、访问修改器和静态类。
  • 学习在使用dart作为首选语言时所需要的概念。然而,这些概念对于我们能想到的任何编程语言都是一样的,只是使用不同的语法表示。

前提条件

要学习本教程,读者应具备以下条件。

  • 对任何编程语言(如Java、Python或JavaScript)的编程和基本编程概念的基本理解。
  • 对Dart编程语法的基本了解,它将是本教程中作为样本使用的语言。

Dart编程语言

Dart是一种优化的客户端多平台编程语言,用于开发由谷歌开发的快速应用程序,以灵活的运行时间执行平台。Dart语言是类型安全的,所以我们在声明变量或修改器时,必须指定存储在内存中的数据类型,这被称为良好的类型化。

虽然类型是必不可少的,但在Dart中,由于类型推理的存在,类型规定是可选的。这为我们提供了一种灵活的方式来定义我们的变量,并且可能非常有用,因为我们可能不确定我们所期望的数据类型。

在运行时使用关键字dynamic 和类型比较,我们可以在未知类型出现时适应它。

类和对象

面向对象的编程(OOP)使我们能够开发大规模的软件,而OOP的一个主要概念就是类。类是一个可编程的概念,它定义了对象的属性和行为,可以用编码语法表示。

它们是描述一个对象的能力的蓝图或定义。一个对象不能执行其类中没有定义的任何能力或功能。一个类是一个模板、蓝图或合同,它定义了一个对象的数据字段或方法。

比如说。

    class Person {
        String name = ‘Andrew’;
        Int age = 23;

        String speak (String words){
            print(“What I am trying to say is, ” + words);
            return (“What I am trying to say is, ” + words);
        }
        String sayAge (int myAge ){
            print(“My age is, ” + myAge);
            return (“My age is, ” + myAge);
        }
    }

数据字段定义了该类的特性或属性(被称为对象的状态)。

String name 和 都是数据字段,成为简单类 的属性。由该类创建的对象的行为或动作以方法/函数的形式表示。在创建该类的实例时使用的与该类同名的默认方法被称为 "构造 "函数。int age Person

String speak 和 ,都是该类 可以执行的行为。方法代表它们。String sayAge Person

这两者都是有意义的,因为如果我们在创建一个人的实例时,从整体上看,对象表示是一个人,是一个个体。他/她有像名字和年龄这样的属性,并且可以执行一些行为,比如说话,表达他们的年龄,等等。

具有相同类型的对象是用一个标准的类来定义的。从一个类中创建的对象被称为一个类的实例。它拥有自己独特的身份、数据字段和功能,作为一种重申,它与从同一个类实例化的其他对象不同。每个对象都是从一个类中实例化出来的。除了dart编程语言中的NULL,所有的类都是从对象中降生的。

所以从上面的类人的例子来看,如果我们从这个类中实例化一个对象或多个对象,每个对象都会有独特的属性(名字,年龄)和独特的行为(说话,sayAge)。

实例化一个对象

在其他编程语言如Java中,我们使用一个独特的关键字 "new "来从一个类中实例化一个对象。然而,在dart中,它的愿望是适应来自严格类型的语言(如Java)的程序员。同样,来自松散类型的程序员,如JavaScript,我们可以在Dart编程语言的第二版中不使用 "new "关键字来实例化一个对象。因此,我们可以使用以下任何一种方法从Person类中创建对象。

var P1 = Person();

var P2 = new Person();

然后我们可以使用单个实例变量P1或P2调用该对象的各个属性和行为。

P1.name
P1.age

结果 - 安德鲁, 23

P2.name
P2.age

结果--安德鲁,23岁

注意,在这种情况下,它们都给出了相同的输出结果。虽然输出是一样的,但它们不是相同的值。P1是一个私人实体,名字是 "安德鲁",年龄是 "23"。同样,P2是另一个私人实体,名字是 "Andrew",年龄是 "23"。

以上不是问题,我们可以使用我们建立的存在于每个类中的构造函数方法来创建具有不同名字和年龄的其他人物实体。

构造函数

如前所述,每个类都有一个隐藏的默认方法,称为构造函数,用于实例化一个给定的类。我们可以指定我们的构造函数,它必须遵循以下指令才能被标记为一个构造函数。

  • 必须是方法//函数。
  • 必须与类本身具有相同的名称。
  • 不能有一个指定的返回类型。
  • 可以在其函数括号中吸收参数。

当参数被指定时,构造函数就是自定义构造函数。如果在函数括号中没有指定参数,所述的构造器会覆盖dart提供的默认构造器方法,并执行自己的方法体。

    class Person {
        String name = ‘Andrew’;
        Int age = 23;
        Person(){
		    this.name = this.name.toUpperCase();
		    this.age = this.age + 3;
        };
        Person(String nameNew, Int ageNew) {
	        this.name = nameNew;
            this.age = ageNew;
        };
        Person (this.name, this.age);
    }

在上面的例子中,我们有三个构造函数:我们的自定义构造函数。

第一个Person构造函数覆盖了默认的构造函数,无论何时Person类被用来创建一个对象。因此,任何使用Person类创建的对象都会有一个 "ANDREW "的名字属性和一个 "26 "的年龄。

    var P1 = Person();
	P1.name;   -  result = “ANDREW”
	P1.age;    -  result = 26

第二个Person构造函数规定,我们可以用我们想要的数据字段name和age的值来创建一个Person对象。当参数被传递时,它会更新数据字段。指定的this 关键字指的是类本身,在本例中是Person

	var P2 = Person(“Moses”, 30);
	P2.name;   -  result = “Moses”
	P2.age;    -  result = 30

第三个Person构造函数指定我们可以用我们想要的数据字段name和age的值来创建一个Person对象,这与我们的第二个构造函数非常相似。这是我们的第二个构造函数,但这里dart为我们提供了一个速记的书写方法。这个构造函数被称为命名构造函数

	var P3 = Person(“David”, 28);
	P3.name;   -  result = “David”
	P3.age;    -  result = 28

访问修改器

访问/可见性修饰符可以用来指定一个类和其成员的可见性。在像Java这样的编程语言中,可以利用public、protected和private等关键字来指定一个类的数据字段或方法的可见性范围。

然而,在Dart中没有特定的关键字来描述数据字段和方法的公共性、私有性或保护性。Dart反而为我们提供了一种处理方式。所有的数据字段默认都是公开的,但是可以通过在指定的修饰符前添加下划线"_"来限制为私有修饰符。

任何以这种方式开始的修饰符将被处理为私有访问级别的数据类型,并且只在Dart库内使用。一个Dart库是一个单一的Dart文件,可以通过使用 "import "关键字来获取它,从而在另一个文件中使用。

// student.dart

    class Student{
        String fullName;
        String email;
        String _password;
        Student(this.fullName, this.email, this._password);
    }
    
    // main.dart
    import student.dart
    void main (){
        Student s1 = Student(“Naomi”, “naomiAdama@gmail.com”, “Abcd1234”);
        print(s1.fullName);    // returns = Naomi
        print(s1.email);	// returns = naomiAdama@gmail.com
        print(s1._password);	// returns a compile error that the setter or getter is not defined for the class.
    }

s1.password返回一个错误,因为我们试图访问其库(其文件)之外的一个私有数据字段。为了解决这个问题,我们需要进行一个封装(后面会讨论)。

静态类与实例变量

到目前为止,我们所研究的所有例子都是处理实例变量的方案。实例变量持有一个对象;它们在dart中可以使用或不使用new关键字来创建,在Java中则使用new关键字。在实例变量上调用的属性和函数都是实例变量属性和实例变量函数。

    var P1 = Person();
    P1.name;   -  result = “ANDREW”
    P1.age;    -  result = 26

P1.name 和 都是P1变量的实例属性。P1.age

静态类是具有静态指定的属性和函数的类。当一个数据字段或函数被指定为静态时,我们指示这个特定的属性或函数属于类本身,而不是属于任何实例对象。

它可以在不创建一个对象的情况下被访问。静态关键字允许一个类的属性和函数在所有的类实例中保持数值。

class Staff {
  static var staffDept;
  var staffName;

  Static void displayDetails() {
    print("Name of Staff is: ${staffName}");
    print("Staff Department is: ${staffDept}");
  }
}

// Main function
void main() {
  Staff stf1 = Staff();
  Staff stf2 = new Staff();
  Staff.staffDept = "HR"; // Static property called
  
  stf1.staffName = “Saul”;
  Staff.displayDetails(); 
}

不需要实例化一个对象来访问一个静态数据字段或调用一个静态方法:要调用一个类的静态成员,在静态数据字段或函数名称前附加该类的名称来使用它们。

正如在上面的例子中所看到的,Staff.displayDetails() 被称为工作人员类的一个静态变量。

继承

继承,就像在现实生活中的表现一样,是一种类可以获得另一个类中定义的属性和方法的方式。使得从一个已经存在的类中创建一个新的类。被继承的类被称为超类,而被继承的类被称为子类。

继承在dart中是通过@override元标记来模拟的,并通过一个扩展关键字来实现。

class Animal{
void movement(String moveMode){
    print("Movement is through  " + moveMode);
  }
}

class Dog extends Animal{
    // No implementation
}
  
class Bird extends Animal{    
    // No implementation
}
  
class Fish extends Animal{
    // No implementation
}


void main() {
  var animal1 = new Dog(“Running on Four legs”);
  animal1.movement();

  var animal2 = new Bird(“Flying with wings”);
  animal2.movement();

 var animal3 = new Fish(“Swimming with Fins”);
  animal3.movement();
}

在这里,由于Dog、Bird和Fish类都是从Animal ,它们都可以访问其父类中定义的属性和方法。因此,狗类、鸟类和鱼类可以调用动物类中的运动方法而不会有任何错误。

继承背后的想法是,具有标准功能和属性的类可以在一个地方/类中声明和实现,并在任何其他文件中使用。

封装

封装是OOP的一种范式,它使我们能够通过防止外部操作直接访问一个类的数据字段来隐藏其值,从而暴露出隐藏的实现细节。简而言之,封装允许程序员隐藏和限制对数据的访问。

为了实现封装。使用私有访问修改器声明数据字段。在dart的情况下,使用下划线前缀修改器("_")。创建公共的getters和setters,允许对这些变量进行间接访问。

使用与访问修饰符部分相同的例子。

// student.dart
class Student{
	String fullName;
	String email;
	String _password;
	Student(this.fullName, this.email);
 
	void setPassword(String pass){
		this._password = pass
	}
	String getPassword(){
		return this._password
	}
}

学生类的_password不能在学生类之外被编辑或修改,这就保证了数据被保护。

抽象

类的抽象是将类的实现与类的使用分开。内部的实现被封装起来,对我们来说是隐藏的。一个典型的例子是dart内部创建的方法被提供给我们使用。例如,toUpperCase() 一个字符串类型或.map() Dart的数组方法。

String name = “Tems Vibes”;
name.toUpperCase();

这些方法的实现对我们来说是未知的。使用的数据字段和它如何执行其功能是隐藏的,我们不需要关心它们。我们只需要知道这个函数是如何工作的,它需要什么作为参数,以及它返回什么。

多态性

多态性是指一个对象能够以一种以上的形式存在的能力。多态性在dart中最突出的使用是当一个子类实例对象使用超类的引用类型进行实例化。

从我们上面的例子来看。

class Animal{
void movement(String moveMode){
    print("Movement is through  " + moveMode);
  }
}

class Dog extends Animal{
    // No implementation
}

class Bird extends Animal{    
    // No implementation
}
  
class Fish extends Animal{
    // No implementation
}


void main() {
  var animal1 = new Dog(“Running on Four legs”);
  animal1.movement();

  var animal2 = new Bird(“Flying with wings”);
  animal2.movement();

 var animal3 = new Fish(“Swimming with Fins”);
  animal3.movement();
}

由于多态性,因为鸟类、狗类和鱼类是由动物类扩展而来,任何子类的对象都可以用父类作为参考类型来创建。

Animal animal4 = Bird(“Flying with wings”);
Animal animal5 = new Dog(“Running on Four legs”);
Animal animal6 = Fish(“Swimming with Fins”);

所有这些都将创建一个个别子类的实例对象。

总结

本教程对编程的概念进行了深入描述。所有这些概念都是我们在面试和在日常生活中开发软件时需要的关键概念。

无论使用何种编程语言,这些概念都是一样的。掌握这些概念可以使我们有资格成为真正的高级别的软件开发人员。