第6章 LabVIEW面向对象程序设计

合集下载

第6讲 LabVIEW界面程序设计1

第6讲 LabVIEW界面程序设计1
• 程序框图的结构应该是越简单、越单一,越容易被人理解越好。
• 对于界面VI的程序框图而言,在循环事件结构外,应该只保留极 少量必不可少的节点,其他的代码统统移至循环事件结构内。初 始化和收尾可以被看做两个自定义事件,需要时发出事件,然后 跳至事件结构中相应的分支去处理即可。改进后的程序如下图所 示:
是不会产生值改变事件的。如果希望在程序中改变控件值的同时
也让它发出值改变事件,可以把值赋给控件的“值(信号)”属 性该数值控件会产生一个值改变事件。
• 用户在抛出“用户事件”时,需要给这个事件指定一个“事件名”。 循环事件结构捕获到这个事件后,跳入“用户事件”处理分支。在处 理这个事件之前,首先查看一下“事件名”,然后再根据“事件名” 对事件做不同的处理。
6.3 耗时代码的处理
• 界面程序不要把耗时较长的代码放在循环事件结构内,每个事件 处理分支内代码的执行时间尽量不要超过200ms,否则,当程序 停留在某一事件处理分支内长时间执行这段代码,程序无法立即 响应其他事件,用户可能误认为程序已崩溃或死锁。
• 下图是对初始化事件程序的改进方案。
• LabVIEW也自带实现了类似功能的VI,程序中可以直接使用自带VI。类似 VI在路径“[LabVIEW]\resource\importtools\Common\Event\Method”中。
• 下图为使用此VI的程序,”Create Event.vi”输入的参数相连的”Event in” 是“类”常量。
• 仅锁住用户界面是不够的,用户会对界面无反应产生疑惑。还有 其他方法,只是暂时忙于处理某事件,无 法处理用户的界面操作。最基本的做法就是把光标设为沙漏状, 这也是windows比较常见的处理方法。
• LabVIEW对光标操作的VI在“编程-对话框与用户界面光标” 中。

《面向对象程序设计》教案

《面向对象程序设计》教案

《面向对象程序设计》教案一、教案简介本教案旨在帮助学生掌握面向对象程序设计的基本概念、原理和方法,培养学生的编程能力和软件开发思维。

通过本课程的学习,学生将能够熟练运用面向对象的编程语言,如Java或C++,进行软件开发和设计。

二、教学目标1. 了解面向对象程序设计的基本概念,如类、对象、封装、继承和多态等。

2. 掌握面向对象程序设计的基本原则,如单一职责原则、开闭原则、里氏替换原则等。

3. 学会使用面向对象的编程语言进行程序设计和开发。

4. 培养学生的软件开发思维和团队协作能力。

三、教学内容1. 面向对象程序设计的基本概念1.1 类与对象1.2 封装1.3 继承1.4 多态2. 面向对象程序设计的基本原则2.1 单一职责原则2.2 开闭原则2.3 里氏替换原则2.4 接口隔离原则2.5 依赖倒置原则3. 面向对象的编程语言3.1 Java3.2 C++4. 面向对象的设计模式4.1 创建型模式4.2 结构型模式4.3 行为型模式四、教学方法1. 讲授法:讲解面向对象程序设计的基本概念、原理和编程方法。

2. 案例分析法:分析实际项目中的面向对象设计案例,让学生理解并掌握面向对象的设计思想。

3. 实践操作法:让学生通过编写代码,亲身体验面向对象程序设计的流程和方法。

4. 小组讨论法:分组进行讨论,培养学生的团队协作能力和解决问题的能力。

五、教学评价1. 课堂参与度:评估学生在课堂上的发言和提问情况,了解学生的学习兴趣和积极性。

2. 课后作业:布置相关的编程作业,检查学生对面向对象程序设计知识的掌握程度。

3. 项目实践:评估学生在团队项目中的表现,包括代码质量、设计思路和团队协作能力。

4. 期末考试:全面测试学生对面向对象程序设计知识的掌握情况。

六、教学资源1. 教材:推荐《Java面向对象程序设计》、《C++ Primer》等经典教材。

2. 在线资源:提供相关的在线教程、视频课程和编程练习平台,如慕课网、Coursera、LeetCode等。

LabVIEW中的面向对象编程技术

LabVIEW中的面向对象编程技术

LabVIEW中的面向对象编程技术在LabVIEW中的面向对象编程技术LabVIEW是一种基于图形化编程的工程软件。

它以图形化的方法创建程序,主要用于测试、测量和控制应用。

除了其强大的数据采集和处理能力外,LabVIEW还提供了面向对象编程(Object-Oriented Programming,简称OOP)技术,使得开发人员能够更加高效和灵活地设计和实现复杂的应用。

本文将介绍LabVIEW中的面向对象编程技术及其应用。

一、面向对象编程技术简介面向对象编程是一种软件开发方法,它以对象为基本单位,通过封装、继承和多态等特性,将程序的数据和对数据的操作进行有机的结合,使得程序的设计更加模块化、可复用和易于维护。

在LabVIEW中,面向对象编程技术被应用于虚拟仪器对象(Virtual Instrument Object,简称VI)的设计和开发。

VI是LabVIEW 程序的基本单位,通过面向对象的思想,可以将VI的功能、数据和界面封装成一个独立的对象,从而实现对其进行灵活的组合和重用。

二、LabVIEW中的面向对象编程1. 类和对象在LabVIEW中,类是面向对象编程的基本概念。

类定义了对象的属性和方法。

对象是类的实例,每个对象都有自己的属性值和方法。

2. 封装封装是面向对象编程的核心思想之一,它可以隐藏对象的实现细节,使得对象的使用者只需关注对象的接口。

在LabVIEW中,封装可以通过访问控制功能来实现。

例如,可以将某些属性设置为只读或只写,以限制对属性的访问权限。

此外,还可以使用属性节点来对属性进行封装,只允许通过特定方法对属性进行访问。

3. 继承继承是面向对象编程的另一个核心概念,它可以通过扩展已有的类来创建新的类,从而实现代码的重用和扩展。

在LabVIEW中,可以通过创建派生类来实现继承。

派生类继承了基类的属性和方法,并可以在此基础上进行扩展和修改。

通过继承,可以实现对现有功能的改进和功能的复用。

LabVIEW的面向对象编程指南

LabVIEW的面向对象编程指南

LabVIEW的面向对象编程指南LabVIEW是一款强大而灵活的图形化编程语言,广泛应用于数据采集、信号处理、测量与控制等领域。

而实现这些功能的关键就是面向对象编程(OOP)。

本文将深入探讨LabVIEW中的面向对象编程,为您提供一份指南,助您在LabVIEW中灵活运用面向对象编程技术。

1. 面向对象编程的基本概念面向对象编程是一种将现实世界的事物抽象成“对象”,并通过定义对象的属性和行为来实现系统开发的编程方法。

在LabVIEW中,对象是基于类(Class)的概念进行创建和使用的,每个类都有自己的数据和方法。

2. 类和对象的创建在LabVIEW中,类是创建对象的模板,是一种用户自定义的数据类型。

通过定义类的数据成员(属性)和方法(行为),可以实例化一个对象。

通过面向对象编程,可以封装数据和方法,实现代码的可重用性和扩展性。

3. 封装和继承封装是面向对象编程的核心概念之一。

它指的是将数据和方法封装在类内部,通过接口提供对外访问。

在LabVIEW中,可以使用“公共接口”来定义类的公共方法和属性,使得其他开发者可以通过对象调用这些方法和属性。

继承是指一个类可以继承另一个类的属性和方法,可以减少代码的重复编写,提高代码的复用性。

4. 多态性多态性是面向对象编程的另一个重要概念。

它可以通过定义一个通用的接口,让不同类的对象都可以实现该接口,并根据对象的不同实现调用不同的方法。

在LabVIEW中,可以使用动态调度方法,通过接口调用对象的方法,实现多态性的效果。

5. 事件驱动编程除了封装、继承和多态性,LabVIEW中的面向对象编程还支持事件驱动编程。

通过定义事件和事件处理程序,可以实现对象间的交互和通信。

当事件发生时,LabVIEW将自动调用相应的事件处理程序,对事件进行响应和处理,提高系统的灵活性和响应性。

6. 错误处理和调试在面向对象编程中,良好的错误处理和调试技术是不可或缺的。

LabVIEW提供了一系列的错误处理工具,如错误处理节点和自定义错误码等,可以帮助开发者在程序运行过程中及时捕获并处理错误。

精品课件-LabVIEW编程与项目开发实用教程-第6章 LabVIEW高级编程

精品课件-LabVIEW编程与项目开发实用教程-第6章 LabVIEW高级编程
图6-1 公式节点选板图6-2 添加输入输出图6-3 公式节点
第6章 LabVIEW高级编程
Байду номын сангаас2.输入公式
公式节点中代码的语法与C语言非常接近,但是只能实现基 本的逻辑流程和运算,不能对文件或设备进行操作或通信,且 代码中没有输入输出语句。公式节点中代码主要有以下几种语
句:
1)变量声明:float a; a+=b;
第6章 LabVIEW高级编程
图6-9 节点创建和添加输入输图出6-10 Matlab节点应用(左图 为LabVIEW波形图,右图为Matlab Plot图)
第6章 LabVIEW高级编程
6.2.2 MATLAB Script节点实例
【例6-3】Matlab节点创建复杂函数曲线
由于Matlab运算是基于 向量和矩阵的,因此程 序不需要增加LabVIEW 循环结构,直接通过右 键快捷菜单为输出变量 y选择1-D Array of Real类型,见图6-10。
y1 5sin(x / b) exp(-x / (m / b)) y2 cos(x / m) b
图6-8 程序框图和曲线
第6章 LabVIEW高级编程
6.2 MATLAB脚本节点
LabVIEW中的公式节点可以实现一些基本的数学运算,如果 涉及到比较复杂的数学运算,则可以调用Matlab的脚本文件( m文件)来实现。
第6章 LabVIEW高级编程
第6章 LabVIEW高级编程
6.2.1 MATLAB Script节点
Matlab节点位于 函数→数学→公式与脚本 脚本 子选板 内,添加Matlab节点的方式和前面章节中添加公式节点的方式 类似,见图6-9。
向Matlab脚本节点输入Matlab文件的方法有两种: 一种是直接在框内写入文件代码; 一种是在Matlab节点的边框上单击鼠标右键,在弹出的快 捷菜单中选择 导入 选项,在弹出的对话框中选择待输入的 Matlab脚本文件。 Matlab节点输入/输出变量的添加和公式节点类似,分别在 快捷菜单中选择 添加输入/添加输出 选项实现。和公式节点 一样,用户可以为Matlab脚本节点的每个输入/输出变量添加

《LabVIEW 程序设计教程》课件第6章 LabVIEW高级编程

《LabVIEW 程序设计教程》课件第6章 LabVIEW高级编程
一个前面板控件创建多个局部变量,其中一些是写模式,另一些是 读模式。在这种情况下要注意访问各个局部变量的顺序,以免程序出现 读写异常。一般可以用顺序结构,或通过连线关系人为地建立数据的依 从关系。
第6章 LabVIEW高级编程
【例6-4】滑动杆控制温度。
程序一开始运行,滑动杆的初始值就记录在数字显示控件“初始值” 内,滑动“滑动条”改变温度,如果温度超过上限30时,程序“超高”会亮 起,弹出对话框并结束程序。本例中,在两个地方使用了滑动杆控件的 局部变量,且为读属性。
第6章 LabVIEW高级编程
6.3.1 局部变量
1.局部变量创建与编辑
(1)鼠标右键单击一个前面 板中已有的对象,从弹出的快 捷菜单中选择 创建局部变 量 选项,便可创建为该对象 一个局部变量,如图6-11左。
(2)通过函数模板建立局部 变量。如图6-11右所示,选择 结构 局部变量 并将其拖放 到程序框图上。此时局部变量 的图标为 ,在图标上单击右 键弹出快捷菜单,选择 选择 项 数值。
第6章 LabVIEW高级编程
1.全局变量创建
建立全局变量也有两种方法,但比局部变量复杂。 (1)通过函数模板的结构子模板创建
在 函数结构 选板中选择全局变量节点,放置在后面板,此 时图标为
在图标上右键单击选择 打开前面板 或双击,打开全局变量程 序的前面板,在前面板上按照需要的数据类型加入控件,然后将 此程序关闭并保存为一个独立的文件;
第6章 LabVIEW高级编程
6.3.2 全局变量
局部变量与前面板上已有的某一个控件相联系,用于在一个程 序的不同位置访问同一个控件,实现一个程序内的传递数据。
全局变量用于不同的程序之间的数据传递,这些程序可以是并 行的,也可以是不便于通过接口传递数据的主程序和子程序。全 局变量的控件是独立的,它需要一个特殊的程序作为自己的容器 。因此可以说全局变量是一个内置的G语言对象。

LabVIEW面向对象编程技术

LabVIEW面向对象编程技术

-1$#’34 继承方式下 ! 基类的公有成员和保护成员在派
生类中为私有类型 " 但是 &’()*+, 中只有 -.(/$0 继 承方式 ! 只要存在继承关 系 ! 那 么 必 定 是 -.(/$0 继 承 方式 " 这是因为 &’()*+, 的开发者认为在实际编程 工作中 ! 保护继承与私有继 承的使用是极少的 ! 它们 只在技术理论上有意义 " &= $ 多重继承
收稿日期 "#--./!#/#修稿日期 "#--0/-1/-#
图 < 创建一个汽车类对象
在 #$%&’() 中既没有构造函数 " 也没有析构函 数的概念 & #$%&’() 定义类时 " 类中的用于定义数据 的控件 " 如图 9 中的 A3,.4.%-05;B,0 中的前面板中各 种数据的默认值就是数据的初始化 & 如果不采用默认
&’()*+, 中使用 . 静态 &B3’3$0 $/ 这个术语来描述
的 方 法 ! 跟 % // 中 描 述 的 . 静 态 / 含 义 完 全 不 同 -
&’()*+, 认为一个静态方法 &B3’3$0 C43D25 $ 就是一个
简单的子 #$&B.(#$$ 的调用 -
现 代 计 算 机 ! 总 第 二 八 一 期 "
%// 允许多重继承 ! 即分别从类 > 和类 ? 继承得
到类 %! 类 % 代表了类 > 和类 ? 的合成 ! 其同时具有 两个类的特征 " 而 &’()*+, !@< 中没有类似多重继承 的机制 !&’()*+, 的开发者认为在 &’()*+, 中 使 用 多重继承所能解决的问题和它所带来的问题一样多 ! 因此没有计划在以后的版本中推出该功能8A9" &" $ 实现对私有数据继承的方法

LabVIEW面向对象高级编程

LabVIEW面向对象高级编程

LabVOOP Design Patterns (version 1.0) Stephen Mercer, LabVIEW R&D, National InstrumentsTable of ContentsIntroductionThe PatternsSingletonFactoryHierarchy CompositionDelegationAggregationSpecificationChannelingVisitorConclusionIntroductionWhen talking about computer programming, a design pattern is a standard correct way to organize your code. When trying to achieve some particular result, you look to the standard design patterns first to see if a solution already exists. This sounds a lot like an algorithm. An algorithm is a specific sequence of steps to take to calculate some result from a set of data. Generally algorithms can be written once in any given programming language and then reused over and over again. Design patterns are rewritten over and over again. For example, in house cleaning, consider this algorithm for vacuuming a carpet: “Start in one corner, walk horizontally across the floor, then move to the side and continue making adjacent parallel stripes until the whole floor is vacuumed.” Compare this with the design pattern for cleaning a room: “Start cleaning at the ceiling and generally work your way down so that dirt and dust from above settle on the still unclean areas below.” Design patterns are less specific than algorithms. You use the patterns as a starting point when writing the specific algorithm.Every language develops its own design patterns. LabVIEW has patterns such as “Consumer/Producer Loops” or “Queued State Machine.” These are not particular VIs. Many VIs are implementations of queued state machines. When a LabVIEW programmer describes a problem, another programmer may answer back, “Oh. You need a queued state machine to solve that problem.” Starting in LabVIEW 7.0, LabVIEW has had VI Templates for many LabVIEW design patterns available through the File>>New… dialog. With the release of LabVIEW Object-Oriented Programming, we need to find the new patterns that arise when objects mix with dataflow.The seminal text on design patterns appeared in 1995: Design Patterns by Gamma, Helm, Johnson and Vlissides. This text is colloquially known as “the Gang of Four book.” This text focused on object-oriented design patterns, specifically those that could be implemented using C++. Many of those patterns are predicated on a by-reference model for objects. As such they apply very well to classes made with the GOOP Toolkit (or any of the several other GOOP implementations for LabVIEW). LabVIEW classes, added in LV8.2, use by-value syntax in order to be dataflow safe. This means that the known patterns of object-oriented programming must be adapted, and new patterns must be identified. This document describes the LabVOOP-specific patterns I have identified thus far.This document is not on NI’s DevZone as I do not wish to give an official imprimatur to these yet. The descriptions and methods of implementation may not be as optimal. I am posting these as a common LabVIEW user, not as a member of LabVIEW’s R&D team.– Stephen Mercer Reference:Design Patterns Gamma, Erich, et al. 1995.Addison Wesley Longman, Inc.Singleton Pattern(adapted from Gang of Four’s Singleton pattern)IntentGuarantee that a given class has only a single instance in memory, that no second instance can ever be created, and that all method calls refer to this single instance.MotivationWhen you create a class, sometimes it is advantageous to guarantee that a program always refers to the same global instance of the class. Perhaps the class represents a database. It would be unfortunate if some section of code accidentally instantiated its own database and thus failed to update the global database. Creating a global means all VIs can access the data. But it does not mean that all VIs will access the global. This pattern describes a framework of classes that guarantee that single instance of data.ImplementationSee/SingletonPattern.zip(An example of this pattern shipped with LV8.2, but that example is flawed, a problem I did not realize before we released: <labview>\examples\lvoop\SingletonPattern\Design Pattern.lvproj )In this implementation, we seek to guarantee a single instance of Data.lvclass. We achieve this by putting Data.lvclass into an owning library, Singleton.lvlib, and making the class private. Now no VI outside the class can ever drop the class as a control, constant or indicator, so we guarantee that all operations are limited to this library. Callers can use Singleton.lvlib:Checkout.vi to get the current value of the data, modify it using any of the operations defined by Singleton.lvlib and then set the new value with Singleton.lvlib:Checkin.vi. The public functions are the same functions that would normally be on the class itself. They are moved to the library so that the functionality is exposed without allowing the class itself to be dropped. Checkin.vi and Checkout.vi use a single-element queue to guarantee only one copy in memory at a time. While the element is checked out to be modified by some routine, no other operation can proceed, thus guaranteeing serial access to the data. Editorial CommentsI do not like the implementation that shipped with LV8.2. In the time since LV8.2 released, I have found better ideas. This “post-release discovery” is one reason why more design patterns are not included with the shipping product. LabVOOP is too new, and many of the patterns identified during development may be found faulty when exposed to a wider audience (i.e. real customers). So I’m making this implementation available.The only hole in the above solution that I can find is VI Server. VI Server could get a reference to the Front Panel controls of Singleton’s member VIs and use the Value property to effectively manipulate a different instance of the class than the one in the queue. Would using Subroutine Priority prevent VI Server access? I think so, but that seems like a pretty odd way to fix these VIs. The fix may not be that necessary – I doubt that many people are going to attempt such a hack on the class. Anyone trying it is already aware that they’re working against the design of the class and may break components that depend upon the singleton nature.Factory Pattern(adapted from Gang of Four’s Factory pattern)IntentProvide a way to initialize the value on a parent wire with data from many different child classes based on some input value, such as a selector ring value, enum, or string input. This may include dynamically loading new child classes into memory. Ideally new child classes can be created and used without editing the framework. MotivationData comes from many sources – user interface, network connection, hardware – in a raw form. This data frequently comes in types, and the data is to be handled generically but each type has a specific behavior at the core of the handling. Such a problem cries out for the use of classes and dynamic dispatching. We want to write an algorithm around some common parent type and then let dynamic dispatching choose the correct subVI implementation for the parts of the algorithm that are type specific. The hard part is in initializing the right class from the input data.ImplementationAn example of this pattern was made available by Christina Rogers in her refactoring of the Getting Started Window in the Init From XML methods. Information about this example is available here:/2006/08/object-oriented-getting-started-window.htmlThe general idea is this: Use your data to identify which class you are interested and get the name and/or path to that class’ file. Then use the Application Properties to get access to that class. Suppose we name our parent class Generic Plugin.lvclass. All of our data will be wrapped by specific child types of Generic Plugin. After we have chosen the path to the child class, we proceed as follows:1.Open reference to the .lvclass file on disk. This returns a LVClassLibrary refnum.2.Get the default instance of the class.3.Cast the LabVIEW Object that gets returned to your plug-in data type.From there you would wire the chosen class instance to an Init method of the class which would take your data as an input. The advantage of this system is that the child class is only loaded into memory if someone actually wants to instantiate that child. If you have a great many possible types of data, this can save on memory and load time for your application. The name of this pattern comes from the fact that a single VI serves as a factory to produce all the myriad child types.Editorial CommentsThis implementation does not work in the run time engine because the LVClass refnum does not exist in the runtime engine. Without this, a much less elegant solution must be used. Instead of identifying the path to the class, use your data to pick an enum value, and wire that enum to a case structure. Each frame of the case structure should have a constant of the specific child class. This alternative implementation does not do dynamic loading and requires that all child classes be known and in memory when the VI loads. It further means editing the factory each time a new child class is created.Hierarchy Composition Pattern(adapted from Gang of Four’s Composite pattern)IntentTo represent a single object as a tree of smaller instances of that same object type. Useful for images (an image is made of a set of subimages), file systems (directory contains both files and other directories) and other systems where there is a common aspect to both the whole object and its parts.Motivation“Composition” refers simply to using one class as member data of another class. One class is thus “composed” of another class. The Hierarchy Composition pattern is specifically for times when you are making a class that is going to be composed of smaller instances of itself.ImplementationAn example of this pattern shipped with LV8.2. See<labview>\examples\lvoop\Graphics\Graphics.lvprojThis example includes a class hierarchy for Graphic.lvclass, as shown in the image.A graphic is simply something that can be drawn. Graphic defines a method Draw.vi,which can be overridden by children. There are three children of Graphic. The first twoare straightforward implementations: Point.lvclass and Line.lvclass. Each of these twohave coordinate data as their member data, and implement Draw.vi accordingly. Thethird class, however, is Collection.lvclass. Collection has as its private data an array ofGraphics. That is, Collection, which is itself a Graphic, contains other Graphics. It’simplementation of Draw is to loop over that array and call Draw for each containedelement. The demo shows how a Collection graphic can be built up from individualpoints and lines.You could continue this, adding a Collection inside a Collection, nesting them to createmore complex Graphics.The difficulty arises when trying to call Draw for a Collection that contains another Collection. This is a recursive call to Collection.lvclass:Draw.vi. LabVIEW does not support recursion and will abort the VI when the recursion is attempted at runtime. There are ways around this barrier. Exploration of the various pros and cons of the workarounds has been proceeding on the LAVA Forums:/index.php?showtopic=3830Delegation PatternIntentTo have two independent classes share common functionality without putting that functionality into a common parent class.MotivationGood object-oriented design requires each class to focus on its assigned task. A class shouldn’t have member VIs unrelated to its task. If you have two classes that have some shared functionality, the usual solution is to create a parent class that both of them inherit from. Sometimes, however, you already have a class hierarchy created and a new feature comes along. The new functionality needs to be added to two existing classes that either do not have a common ancestor or do have a common ancestor but that ancestor is several generations up and not every descendent of that ancestor should have the new functionality. In some languages you might try multiple inheritance. But even in languages that support multiple inheritance, delegation is generally a better solution.This pattern applies best when you have a dynamic VI inherited from some ancestor and two descendent classes want to override that dynamic VI with exactly the same implementation. Delegation helps you avoid writing the implementation twice, once for each of the two classes.ImplementationAn example of this pattern was made available by Christina Rogers in her refactoring of the Getting Started Window in creation of her Project Wizard class. Information about this example is available here:/2006/08/object-oriented-getting-started-window.htmlThe general idea is this: Create a third class that has the new functionality. The new class is frequently something like “Function Helper” or “Function Assistant,” where “Function” is whatever functionality is to be delegated. Give that class all the data fields necessary to carry out the new functionality. Then add that third class as a data member to the two classes that need to share the functionality.The two descendent classes override the ancestor’s dynamic VI. But they only put in a bit of code necessary to call the exact same method on their data member of the helper class. The actual work is entirely in that method of the helper class. Now there is only a single instance of the code, which makes bug fixing easier. The two descendent classes have delegated the work to a third class. Thus the name of this pattern.Editorial CommentsThis pattern is not listed explicitly in the Gang of Four text. The idea occurs as an aspect of several other patterns. I think it is useful enough to warrant specific attention.IntentTo treat an array of objects as a single object.MotivationAn array nicely collects data together into an indexable list. But there are many primitives that operate on an array: Build Array, Remove From Array, etc. There are times when you want an array to guarantee certain properties, such as:•an array that guarantees that no duplicates are ever inserted•an array that is always sorted•an array that doesn’t allow removing elementsThis pattern creates a class that lets you treat an array of another class as a single object.ImplementationNo examples of this pattern are publicly available yet. Here is a summary of the pattern:Suppose you have Data.lvclass. Now you create ArrayOfData.lvclass. In ArrayOfData’s private data cluster, you add an array of Data. The only operations that can be performed on this array are those that you add to ArrayOfData. To guarantee no duplicates, write Insert Element.vi such that it checks the array for existing values before doing the insert. If you need to make sure the data stays sorted, you can write Insert Element.vi such that it inserts data at the correct position. Whatever functionality you supply – or leave out, as in the case of an array that does not allow removing elements – defines what can happen to the array.The new class represents an aggregation of many instances of another class. Thus the name of this pattern. Editorial CommentThis is an easy pattern to understand, and it is easy to think of the implementation on your own. Not all the patterns are complex systems. Sometimes pointing out the obvious is useful. When planning a new application, you may look at a list of patterns to consider what the best design would be. Having these so-called “obvious” patterns in the list helps remind you that you ought to use them. Because as easy as this pattern is, it is easier just to have a raw array running around on your diagram (you don’t have to write a bunch of accessor VIs to duplicate the functionality already found on certain primitives). There are times when you’ll choose to do that. But as your code gets more complicated over time, you may find yourself wishing that you had wrapped the array up so that you could guarantee certain characteristics.IntentTo have different functionality for a class depending upon some value of the class without updating case structures throughout your VI hierarchy when you add another value.MotivationYour data has some field – perhaps an enum, perhaps a string, perhaps something more complex – and you have a case structure that cases out on that field to decide which of several actions to perform. The data in this field is constant (once you have initialized the class this field never changes). When you find yourself creating a lot of these case structures, or, worse, updating a lot of these structures to add a new case, you should remember this pattern.ImplementationExamples of this pattern occur in just about every shipping example.If the data is constant from the time the class is initialized onward, then you should strongly consider creating a set of child classes. The data in that field is unnecessary data – stop hauling it around the diagram. A class knows its data type. If you need that value, you can get it from some static VI on the class that just returns a constant. Further, those case structures can now be replaced with dynamic subVI calls. For every distinct case structure, create a new dynamic VI on the parent class and put the code that used to be in each frame of the case structure in one of the children’s override VIs. Now when you add a new case, there are no case structures to update. So instead of one monolith class with an enum type, you now have many more specific classes. Thus the name of this pattern.This pattern is frequently used in conjunction with the Factory pattern.Editorial CommentLike the Aggregation pattern, this is an “obvious” pattern. But it is easy to overlook the fact that a piece of data never changes. If data never changes, that data is effectively part of the data type. Clusters that carry around the name of their data or a string representing the source of the data cry out for application of this pattern. This pattern is basically the central use case for class inheritance and dynamic dispatching. It simplifies many very complex VIs and clusters into manageable chunks by giving an easy way to break up the functionality of the case structure across multiple VIs. This pattern is the first one that a new user of object-orientation should learn, and generally the first one to consider when refactoring existing applications.Channeling PatternIntentTo provide a guaranteed pre-processing/post-processing around some dynamic central functionality.MotivationYou have a class hierarchy. And you have some algorithm that you want to implement on the parent class. There is a core step of the algorithm that needs to be dynamic so that each child class can provide its own behavior. But it is unsafe to call that step directly – you want a class interface that guarantees the step is only called from the algorithm VI.ImplementationNo examples of this pattern are publicly available yet. Here is a summary of the pattern:The parent class has the VI that implements the algorithm. Make the algorithm VI a static VI (no dynamic inputs). That way the child classes cannot override the algorithm itself and thereby avoid calling the pre-processing/post-processing. Make the dynamic step of the algorithm a dynamic VI that the child classes can override and make the dynamic VI be protected in the parent class. This forces all the children to use protected scope for their override VIs. No VI outside the class hierarchy will be able to call the dynamic VIs directly. This pattern does not prevent child classes from calling the step on themselves or other child classes without going through the algorithm. It does make sure that all the VIs outside the class hierarchy always go through the algorithm VI.The name of this pattern refers to the control of the flow of data – the data is channeled through the static VI to get to the dynamic VIs.Editorial CommentA customer asked me why all member VIs in classes aren’t dynamic. The performance overhead of dynamic VIs is pretty small (and constant no matter how deep the class hierarchy or how many dynamic VIs there are on the class) such that it made sense to the customer to make all the VIs dynamic and only make static VIs if a performance problem actually arose. That would give maximum flexibility to the class. This pattern is one of several reasons not to make everything dynamic. If the algorithm itself were dynamic, child classes might decide to override the algorithm and skip the pre/post processing. This pattern is particularly useful for large programming teams where you might not know all the developers, or where child classes will be implemented by third parties. It lets the original author put compiler-enforceable guidelines into the code so that future programmers do not unwittingly write VIs that will create issues for the architecture.Visitor Pattern(adapted from Gang of Four’s Visitor pattern)IntentTo write a traversal algorithm of a set of data such that the traversal can be reused for many different operations.MotivationSuppose I have an array of integers. I need a function that will calculate the sum of those integers (ignore, for the sake of argument, the fact that there’s a primitive to do this). I drop a For loop and iterate over every value, adding each element to a running total in an uninitialized shift register. The value in the shift register when the loop finishes is my sum.Now suppose I want to find the product of those integers. I write the same For loop and shift register, only instead of the Add primitive, I use Multiply. Everything about these two VIs is exactly the same except for the core action. How can I avoid duplicating so much code?Dynamic dispatching does not immediately help in this case – I do not have any child types on any of the wires that I can dispatch on. I could make my traversal VI have a VI Reference input. Then, instead of calling a primitive, I could have a Call By Reference node. The VI that I pass in would have either the Add or Multiply primitive.This is helpful, but only works if my two VIs have exactly the same connector pane. What if I need other information, other parameters, to do the job in that Call By Reference node?ImplementationAn implementation of this pattern is available here:/LV2OO_Style_Global_v1.0.zipInstead of taking in a VI Reference, the traverse VI takes in an object of class Action. This is a class that you define. Create one child class of Action for each specific action you want to do during the traversal. Then instead of a Call By Reference node, call the Do Action.vi method. This will dynamically dispatch to the correct implementation. The Action object can have all sorts of data inside it that can augment the operation at hand. You can implement as many new Action children as you want without ever having to change your original traversal framework.The traversal VI can get very complicated, far beyond the simple For loop over an array that I mention here. As the traversal walks over a data set, the Action object “visits” each piece of data and updates itself. Thus the name of this pattern. Your visitor can collect a summary of information about the pieces of data (such as the sum and product calculations), or it might search for a particular value, or it might even modify the data as it visits (divide each value in the array by 2). The traversal works just as well in all of these cases.Editorial CommentI am tired of writing LV2-style globals. These globals are great – very dataflow efficient, very easy to understand. But you have to duplicate the VI every time you want to support a different data type. I figured there had to be a better way. I’ve been thinking about this implementation for a while. It may not be optimal, but I think it is an excellent starting point. Imagine… the possibility of never writing another LV2-style global VI ever again, because you could just reuse one and give it the particular action that you want. A whole new flavor of über-geek nirvana!ConclusionThose are the design patterns thus far. I hope to update the list as time goes by, both with more patterns and with better examples for the existing patterns. Pay attention to the code you write – when you find yourself following the same routine over and over, try giving a name to the pattern. See if you can clearly identify when it is useful and how best to do it.Exploration of these patterns helps us design better code. Using the patterns is using the learning of previous developers who have already found good solutions. In studying the patterns, we can learn what good code “feels” like, and we are then more aware when we create an unmaintainable hack in our own programs.When we follow the standard designs it helps others looking at our code understand what they’re looking at. If a programmer knows the general pattern being used, he or she can ignore the framework and focus on the non-standard pieces. Those are the points are where the program is doing its real work. It is akin to looking at a painting in a museum – the painting is the interesting part. The picture frame and the wall are just there to hold up the art. If the frame or wall are too decorative, they pull the focus.I do not talk about any anti-patterns in this document. Anti-patterns are common attempts that look like good ideas but have some generally subtle problem that will arise late in development. Some anti-patterns in other languages are sufficiently detectable that a compiler could even be taught to recognize them and report an error. Perhaps these exist in LabVIEW. We should be cataloguing these as well.For those who chose object designs,we want the world of wire and nodeto morph naturallyinto a world of class and method.– LabVOOP。

79.LabVIEW 面向对象程序设计的简介

79.LabVIEW 面向对象程序设计的简介

LabVIEW 面向对象程序设计的简介LabVIEW 的数据流驱动模式,与面向过程的编程思想有些类似。

它们都是把程序看成是一组过程或功能的集合,LabVIEW 利用数据流控制这些功能执行的顺序。

由于开发者可以随意的修改、调用这些功能模块,在程序开发的后段,模块之间的划分会变得模糊,依赖关系也变得无序。

这种方式就不再适合大型程序的开发。

面向对象的编程思想是专为解决这个问题提出来的。

面向对象的编程思想大大提高了编程时的灵活性和可维护性。

现在的大型程序中几乎没有不基于面向对象编程思想的。

LabVIEW 为了适应这一趋势,也从8.2 版本开始引入了面向对象程序设计的思想。

面向对象有三大特征:封装、继承和多态。

封装是把高度相关的一组数据和方法组织在一起,形成一个相对独立的类。

外部程序只能通过严格定义好的接口访问类所允许公开的数据和方法;而对于不需与外部发生联系的数据和方法,类会把他们隐藏和保护起来。

这样就避免了编程过程中,函数模块常常被到处滥用以至于难以维护的弊病。

(假如,我们的程序是模拟多只小狗的日常生活的。

在设计程序时,就可以把他们抽象归为“狗”类。

这个类包括了一些属性,如年龄、皮毛颜色、名字等等;还可以包含一些方法,即狗的行为,比如进食、移动、叫等。

)初一看LabVIEW 中的Class 就会发现它很像Cluster,或许它就是在Cluster 基础上发展来的。

C++ 中的Class 也是在Struct 的基础上发展来的,而且,在C++ 中,除了函数默认的权限不同,Class 和Struct 是等效的。

在LabVIEW 中,二者还是截然分开的,Cluster 中只有数据,Class 中除了数据,还可以有方法。

C++ 类中的成员变量可以是私有,也可以是共有;为了安全起见,LabVIEW 中所有的数据都是私有的,必须通过公有的VI才能访问这些数据。

C++ 的类拥有构造函数和析构函数;LabVIEW 的类没有这两个方法。

LabVIEW编程中的面向对象设计与开发方法

LabVIEW编程中的面向对象设计与开发方法

LabVIEW编程中的面向对象设计与开发方法LabVIEW是一种流程式编程语言,广泛应用于数据采集、仪器控制以及测试和测量领域。

面向对象设计和开发方法在LabVIEW编程中起着重要的作用,可以提高代码的可维护性和重用性。

本文将探讨LabVIEW编程中的面向对象设计与开发方法。

一、面向对象编程简介面向对象编程(Object-Oriented Programming,OOP)是一种程序设计范型,主要思想是将现实世界的概念抽象成为对象,并通过对象之间的交互来实现程序的功能。

面向对象编程具有封装、继承和多态等特性,能够提高代码的可读性和可维护性。

二、LabVIEW中的面向对象设计原则在LabVIEW中,可以通过使用面向对象的设计原则来提高程序的可维护性和灵活性。

1. 封装性(Encapsulation):将数据和操作封装在对象中,通过公共接口进行访问。

在LabVIEW中,可以使用类(Class)来实现封装性,将数据和方法封装在类中。

2. 继承性(Inheritance):通过继承机制,可以实现代码的重用,并且方便对代码进行扩展。

在LabVIEW中,可以使用继承关系来实现类之间的关联。

3. 多态性(Polymorphism):通过多态机制,可以实现接口的统一,提高代码的灵活性。

在LabVIEW中,可以使用虚方法(Virtual Method)和动态派生(Dynamic Dispatch)来实现多态性。

三、LabVIEW中的面向对象开发方法1. 创建类(Class):在LabVIEW中,可以通过面向对象的方式创建类。

首先,需要创建一个新的面板,并在控件栏中选择"新增类"。

然后,可以根据需要添加属性和方法,并设置访问权限。

2. 定义类的继承关系:在LabVIEW中,可以通过继承关系来实现代码的重用。

在创建类时,可以选择继承已有的类。

通过继承,子类可以继承父类的属性和方法,并根据需要进行扩展。

7. LabVIEW编程:面向对象编程之设计模式一

7. LabVIEW编程:面向对象编程之设计模式一

Redhead Duck display() { //looks like redhead}
Rubber Duck display() { //rubber duck}
策略模式
重写方法
Duck quack() swim() display() fly() //Other duck-like methods
继承的一种重要用途是实现代码的重用
继承
Mallard Duck display() { //looks like mallard} Redhead Duck display() { //looks like redhead} Rubber Duck display() display() { { //rubber duck} //rubber duck} fly() { //override to do nothing}
继承不易维护
Mallard Duck display() { //looks like mallard}
Redhead Duck display() { //looks like redhead}
Rubber Duck display() { //rubber duck} fly() { //override to do nothing}
Redhead Duck display() { //looks like redhead}
策略模式
Duck quack() swim() display() fly() //Other duck-like methods
橡皮鸭子不能飞
Mallard Duck display() { //looks like mallard}
观察者模式
Stock <<abstract>> Price Symbol Add Observer() Remove Observer() Update()

VFP第6章面向对象的程序设计

VFP第6章面向对象的程序设计

03
Visual FoxPro中的事件 驱动编程
事件驱动编程的概念
事件驱动编程是一种编程范式,它通 过事件来触发程序的执行。在事件驱 动的程序中,事件是由用户操作或其 他系统事件触发的,例如点击按钮、 键盘输入等。
在事件驱动的程序中,程序的状态由 事件和事件处理程序来管理。当某个 事件发生时,相应的事件处理程序会 被调用,以响应该事件。
什么是对象
对象是面向对象程序设计的基本单元,代表了现实世界中的 事物或概念。
对象由属性和方法组成,属性描述对象的状态,方法定义对 象的行为。
对象的属性、方法和事件
属性
描述对象特性的数据元素,如颜色、大小等。
方法
定义在对象上的操作,用于实现特定的功能 或行为。
事件
由用户或系统触发,导致对象状态改变或执 行特定操作。
根据项目需求选择合适的数据访问方式,如直接访问数据 库、使用ORM框架等。
01
数据流控制
设计合适的数据流控制结构,如顺序、 循环、条件等,实现数据的处理和流转。
02
03
数据验证
对输入数据进行验证,确保数据的合 法性和准确性。
THANKS FOR WATCHING
感谢您的观看
为控件编写事件处理程序,以响应用户的操 作或系统事件。
调用方法
通过调用控件的方法来执行特定的操作,如 显示或隐藏控件。
05
面向对象程序设计在 Visual FoxPro中的应用
数据库应用程序的设计
数据库模型选择
根据项目需求选择合适的数据库模型,如关系 型、层次型或网络型。
数据结构设计
定义数据库中的表、字段、主键、外键等,以 及表之间的关系。
事件处理程序

labview面向对象编程项目实例

labview面向对象编程项目实例

labview面向对象编程项目实例LabVIEW面向对象编程(Object-Oriented Programming, OOP)是一种在LabVIEW中使用面向对象设计原则和技术进行软件开发的方法。

本文将介绍一个基于LabVIEW的面向对象编程项目实例,以帮助读者更好地理解和应用这种编程方法。

标题:LabVIEW面向对象编程项目实例引言:在LabVIEW中,面向对象编程提供了一种高效且可维护的软件开发方式。

通过将软件系统划分为多个对象,并通过对象之间的交互实现功能,可以提高代码的可重用性和可扩展性。

本文将以一个简单的实例介绍如何在LabVIEW中利用面向对象编程进行软件开发。

一、项目背景和需求假设我们需要开发一个简单的学生管理系统,该系统需要实现以下功能:1. 添加学生信息(包括姓名、年龄和成绩);2. 查询学生信息;3. 统计学生人数;4. 计算学生平均成绩。

二、面向对象设计为了实现以上功能,我们可以设计以下对象:1. 学生类(Student):包含学生姓名、年龄和成绩等属性,以及添加学生信息和查询学生信息的方法。

2. 学生管理类(StudentManager):包含学生列表、添加学生信息、查询学生信息、统计学生人数和计算学生平均成绩等方法。

三、LabVIEW面向对象编程实现1. 创建学生类我们可以创建一个包含学生属性和方法的学生类。

在LabVIEW中,可以使用类定义来表示一个类。

学生类可以包含以下属性:- 姓名:字符串类型- 年龄:整数类型- 成绩:浮点数类型学生类可以包含以下方法:- 添加学生信息:输入学生属性,将学生信息添加到学生列表中;- 查询学生信息:输入学生姓名,返回对应的学生信息。

2. 创建学生管理类学生管理类可以包含以下属性:- 学生列表:用于存储学生对象的列表。

学生管理类可以包含以下方法:- 添加学生信息:输入学生属性,创建学生对象并添加到学生列表中;- 查询学生信息:输入学生姓名,遍历学生列表,找到对应的学生对象并返回其信息;- 统计学生人数:返回学生列表的长度,即学生人数;- 计算学生平均成绩:遍历学生列表,累加所有学生的成绩并计算平均值。

LabVIEW+面向对象设计

LabVIEW+面向对象设计

适配器模式适配器是常见的硬件概念,比如我们常用的USB转RS232适配器。

我们乊所以采用适配器,主要是由于以下原因:一、原有硬件设备已经存在,新的连接设备不存在和旧设备一致的接口。

二、新的设备需要连接很多不同接口的设备,需要构建一个统一的接口。

OOP适配器模式借用了硬件适配器的概念。

软件的升级换代是非常常见的,对于已经成功运行的软件系统,我们在设计新的软件系统时,不可能完全放弃原有的软件系统。

但是经常遇到的情况是原有的软件系统和新的软件系统具有不同的理念,在考虑到扩展性的同时,必须兼容原有的软件系统,此时适配器模式是我们首选的设计模式。

我们看一下适配器模式的定义:适配器模式将一个类的接口转换成客户希望的另外一个类的接口。

适配器模式使原本不兼容而不能一起工作的类可以一起工作。

适配器模式并非特别的技术,其实质是在新的类中借用(翻译)原有类的动作和行为。

在面向对象的编程中,当然是两个类乊间的关系。

对于LV来说,由于早期不存在LVOOP,因此适配器很少针对两个类,但是适配器模式的设计思想完全可以推广到面向过程和面向对象的混合编程中。

下面我们通过一个绘图类说明如何使用适配器模式。

我们的目的是建立一套通用绘图程序类,包括点、线、圆等等,仍图形的角度看,无论是点还是圆形,都存在很多共同点,比如绘图颜色、画笔等等,因此建立一个形状的类作为基类是非常合适的,在基类的私有数据中存储公共特征,比如颜色和画笔,另外需要在基类中创建一个可重写的绘图函数,这样基类和继承的特殊形状的子类都可以使用同一绘图函数,实现类的多态特性。

我们创建一个形状类作为基类,形状类的私有数据包括画笔和颜色,并分别创建了私有数据的读写属性,形状类中,我们创建了可重写的绘制形状方法。

属性的程序框图非常简单,就不贴图了。

看一下形状类中可重写绘制形状的程序框图。

在基类的绘图函数中,不执行任何实际绘图工作,具体绘图工作延迟到具体子类中实现。

我们知道,绘制一个圆需要圆的半径和圆心,其中圆心是一个点,因此我们创建一个点类,并将点类作为圆类的私有数据成员乊一。

LabVIEW图形化编程-基础与测控扩展课件第6章

LabVIEW图形化编程-基础与测控扩展课件第6章

LabVIEW图形化编程:基础与测控扩展
6.2 常用程序设计模式
状态机工具:
• 使用LabVIEW的状态图工具箱,可以以另一种独特的方式实现状态机编程。
• 安装状态图模块(LabVIEW 2018 Statechart Module)(安装完后,将可以多种方式创 建状态图及其状态机程序)。
• 相对于LabVIEW 8.6版本的状态图工具,LabVIEW 2018版状态图的开发方法有较大变化。
• LabVIEW开放给用户自定义的代码取值范围为5000~9999和-8999~-8000之间的整数。
LabVIEW图形化编程:基础与测控扩展
6.1 程序的错误处理
错误信息处理:
• 默认情况下,错误簇数据传递到末端,即程序中某个函数或子VI的错误簇输出端口没有 与其他模块连接时,当错误簇数据有错误信息,系统将自动弹出一个错误信息提示对话 框。
选择 属性
LabVIEW图形化编程:基础与测控扩展
6.1 程序的错误处理
错误信息处理:
• 必须考虑多个错误簇数流的合并处理。
• LabVIEW提供了一个“合并错误”VI( 一个含有错误信息的错误簇数据。
),其返回的是所有输入错误簇数据中的第
LabVIEW图形化编程:基础与测控扩展
6.2 常用程序设计模式
在生产者/消费者设计模式(事件) 中,生产者是采用事件结构,实现了 一种不定期数据产生方式。而消费者 结构采用的是包含元素出队列的 While循环+条件结构(实现错误处 理)。
生产者/消费者设计模式(事件)
LabVIEW图形化编程:基础与测控扩展
6.2 常用程序设计模式
LabVIEW基本设计模式:
6.2 常用程序设计模式

第6讲 LabVIEW程序设计进阶

第6讲 LabVIEW程序设计进阶
用户动作已发生但尚未处理事件. 允许自定 义事件响应
事件结构的运行机制
• 当运行一个VI时,LabVIEW将自动注册那些已经在事件
结构对话框中配置好的事件
• 当一个已经注册的事件发生时,它将进入事件队列并 等待对应的事件结构代码执行
– 不会错过事件,并且响应事件的先后顺序依照发生的顺序
• 默认情况下,前面板会锁定,直到对应的事件被处理
– LabVIEW中的面向对象编程(OOP)
养成良好的编程习惯
• 程序框图不要太大
– 尽量在一屏中放下,或者至多只需在一个方向上拖动
– 程序如果实在太大,应考虑使用子VI (将在后续介绍)
• 添加必要的注释
清晰直观的子VI风格
Better Good
Best
33
习惯数据流的编程方式
• 有些顺序帧结构可以用状态机替换
• 尽量不要用变量代替连线
利用错误簇
错误解析
• 可以输入错误代码,查看LabVIEW对错误的解释
错误分支
界面设计原则: 清晰直观
• Labels (标签) – 简短说明 (程序框图中也会显示)
• Captions (标题) – 较长的说明
界面设计原则: 清晰直观
• 如有必要,可增加
说明信息
• 避免不必要的使用(比如仅仅为了减少连线)
• 初始化变量(避免出现不确定状态)
避免竞争状态
• 避免同时写入共享资源
• 例: 右边程序的执行结果?
– Value = (Value * 5) +2 – Value = (Value + 2) * 5
– Value = Value * 5
– Value = Value +2
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。


8
6.2LabVIEW与面向对象程序设计
多态
多态性表现有两种,即编译时的多态性和运行时的多态性 。编译时的多态性是用函数的重载来实现的,运行时的 多态性是用虚函数来实现的,而这两种方式在LabVIEW 的类中都没有实现。 首先,LabVIEW类不支持重载,但这种多态性的思想在 LabVIEW的早期版本中就一直存在并发挥着重要作用, 主要表现为多态的函数、VI和单位; 其次,对于虚函数而言,“虚拟”和“虚拟分配”的概 念在LabVIEW中也面临一些问题,LabVIEW面向对象编程 选择了“动态”和“动态分配”来代替这两个术语。

5
6.2LabVIEW与面向对象程序设计
LabVIEW引入面向对象编程时的术语
LabVIEW依然使用家族关系术语:父与子、兄弟与堂兄 弟等,这些都是用户已经熟悉的术语,当提到某个类的 父类时,都可以理解这两个类之间的关系; LabVIEW类成员的限定性术语:依然采用“私有的”、 “共有的”和“受保护的”等词汇。
更改后的 继承关系

15
6.3LabVIEW对象基本实现
创建方法
在类名称上右击,选择需要创建VI的类型:普通成员VI、动态 成员VI或重写VI(Override VI)。

16
6.3LabVIEW对象基本实现
LabVIEW面向对象程序设计
Intelligent Electronics Institute Huazhong University of Science & Technology
目录
面向对象 LabVIEW与面向对象程序设计
LabVIEW对象基本实现
LabVIEW对象高级技巧
实例介绍
提示与建议
在面向对象程序设计中,继承表达的是类之间的关系,这种关 系使得一个类可以继承另一类的属性和方法,从而提供了通过 现有的类创建新类的方法,也提高了软件复用的程度; 多态是面向对象程序设计的重要特性之一,是指不同的对象收 到相同的消息时产生不同的操作行为,或者说同一个消息可以 根据发送消息的对象的不同而采用多种不同的操作行为。
Байду номын сангаас
27
6.4LabVIEW对象高级技巧
在类实现时,LabVIEW需要为一个类分配数据空间

28
6.4LabVIEW对象高级技巧
动态分配
动态分配是LabVIEW的一个特色,一个看似单个VI调用 的节点在运行时实际上调用的是一组VI中的某个,这取 决于运行时动态分配输入端连线上的值; 每一个在连线上传递的对象都含有指向其类信息的指针 ,这个类信息包含了一个“动态分配表”,它是一个VI 引用表; 每个类首先复制了其父类的动态分配表,同时它用自身 重写的VI方法替换父类中对应的方法,然后将没有重写 的父类动态分配VI添加到表中。
私有数 据成员

12
6.3LabVIEW对象基本实现
设置继承
在LabVIEW中,通过“继承”可在现有类的基础上创建 一个新类; 当一个新类被设置为继承另一个LabVIEW类时,这个新 类就可以使用它所继承的类中“公共”及“保护”型的 成员VI; 在LabVIEW中,所有的类都默认继承LabVIEW Object的 基本类。

19
6.3LabVIEW对象基本实现
右击“保研生”类,选择“新建”下拉列中的“用于重 写的VI”,会出现一个提示框用于选择需要重写的动态 VI。我们选择“大四学生”类下的“获取成绩.vi”, LabVIEW会自动生成一个“保研生”类下的“获取成绩 .vi”。

6
6.2LabVIEW与面向对象程序设计
继承
LabVIEW在实现继承特性时坚持这样一条原则:LabVIEW 用户能够实现类的继承,可以选择一个已有类作为父类 ,创建一个子类,并且可以覆盖父类中的方法; LabVIEW提供了(Object)类,作为所有LabVIEW类的祖 先; LabVIEW目前只支持公共继承,而不支持私有继承和多 继承。
使用类获取大一成绩程序框图

25
6.4LabVIEW对象高级技巧
构造函数与析构函数
在一般的面向对象程序设计语言中,对象在创建和销毁 时会自动调用两个函数:构造函数和析构函数;
构造函数的作用是在对象被创建时利用特定的值构造对 象,将对象初始化为一个特定的状态,使对象具有自己 的特征; 析构函数则用来完成对象被删除前的一些清理工作,析 构函数调用完成之后,对象将被销毁,相应的内存空间 也被释放;
在LabVIEW的面向对象编程中,构造和析构是隐含的, 不需要用户编写或调用。

26
6.4LabVIEW对象高级技巧
内存分布
在LabVIEW中,类的高效存储是一个挑战性的问题。 一个类的数据包括从父类继承来的数据簇和自身的私有 数据簇。

21
6.3LabVIEW对象基本实现
动态分派程序
在编写程序时,动态成员VI在程序背面板上就像一般的子 VI一样,不过当运行时,输入端口传递进来的数据就决 定了调用哪个类中的成员VI。

22
6.3LabVIEW对象基本实现
访问范围设置
LabVIEW类只包含私有成员数据,但可以为类的成员VI指 定访问范围。成员VI的访问范围选项包含如下设置: a) 公共(Public),任何VI都可以调用该成员VI; b) 保护(Protected),仅该成员VI所在类及其子类中的 VI可以调用该成员VI,在项目浏览器窗口中受保护的成 员VI图标中有一个暗黄色的钥匙符号; c) 私有(Private),仅该成员VI所在类中的VI可以调用 该成员VI,在项目浏览器窗口中私有型的成员VI图标中 有一个红色的钥匙符号。
“保研生”类 中获取成绩的 程序框图

20
6.3LabVIEW对象基本实现
输入或输出接线端
对于动态VI,右键单击连线板上的输入或输出接线端,会发现其 连接为动态分配模式。
“保研生”类 中获取成绩的 输入端口

习题

2
6.1面向对象
对象与类的概念
对象是系统中用来描述客观事物的一个实体,是构成系 统的基本单位,由属性和对这些属性进行的操作等构成; 类是对象的抽象及描述,是具有共同属性和操作的多个 对象的统一描述体,类也是对象,是一种集合对象;
在类的描述中,每个类要有一个名字,要表示一组对象 的共同特征,还必须给出一个生成对象的实例的具体方法;

10
6.3LabVIEW对象基本实现
私有数据控件示例
类库文件中的 私有数据控件

11
6.3LabVIEW对象基本实现
编辑私有数据成员
在项目浏览器窗口双击类的私有数据控件,可以对类中的数据成 员进行编辑,将需要的控件放置到该类的定义私有数据控件中 ,作为类私有数据簇中的成员。

23
6.3LabVIEW对象基本实现
在类上右击,选择属性后可以设置一个VI的访问范围

24
6.3LabVIEW对象基本实现
使用类
在创建LabVIEW类的实例时,用户可直接将这个类的类库文件 (.lvclass)作为控件或常量放置在相应程序的前面板或程序 框图中; 在LabVIEW类中,所有的私有数据被定义为一个簇,通过在成 员VI的程序框图中调用函数来访问和操作这些数据; 对LabVIEW类进行捆绑或解除捆绑时,节点上仅显示当前类私 有数据的接线端,而不显示从父类继承的数据的接线端。
对象的属性和方法是对象定义的组成要素,它们统称为 对象的特征。

4
6.1面向对象
面向对象中的三要素:
封装 继承
多态
在面向对象的程序设计中,封装就是把相关的数据和代码结合 成一个有机的整体,形成数据和操作代码的封装体,对外只提 供一个可以控制的接口,内部大部分的实现细节对外隐蔽,达 到对数据访问权的合理控制;
类中的每个对象都是该类的对象实例,系统运行时通过 类定义属性初始化可以生成该类的对象实例。

3
6.1面向对象
属性与方法的概念
对象是属性及方法的封装体; 对象的属性是指描述对象的数据,这些数据可以是系统 或用户定义的数据类型,也可以是一个对象的数据类型 ; 对象的方法是指定义在对象属性上的一组操作的集合; 方法是为响应消息而完成的算法,表示对象内部实现的 细节,对象方法集合体现了对象的行为能力;
新建静态成员VI
新建静态成员VI后,会打开一个空面板的VI, 用户可以根据应用需要添加程序代码;
静态方法只有单个VI,在子类中无法创建与父 类静态成员VI相同名称的成员VI。

17
6.3LabVIEW对象基本实现
新建动态成员VI
新建动态成员VI后,会打开一个含有部分代码的VI,其中包括 错误输入簇、错误输出簇、用于错误处理的条件结构,以及输 入LabVIEW类和输出LabVIEW类; 动态成员VI主要出现在具有继承关系的LabVIEW类中,只有当 子类需要继承并重写父类中的某些VI时,这些VI才有必要设置 为动态成员VI。

7
6.2LabVIEW与面向对象程序设计
封装
LabVIEW实现了类的封装,但对封装特征进行了选择; LabVIEW类只包含对私有数据的支持,不提供公共数据 和受保护的数据两种属性; LabVIEW类中的方法,不仅可以是私有的,还可以是公 共的或受保护的。

9
6.3LabVIEW对象基本实现
创建类
通过菜单“File→New→Class”或者在项目浏览器的右 键快捷菜单中选择“New→Class”项,都可以创建 LabVIEW类; 创建类时,LabVIEW将创建一个新的类库文件( .lvclass),该文件可以记录类的私有数据控件( Private Data Control)和所有被创建的成员VI的信息 ,包括VI列表及VI的属性等; 类的数据被定义在私有数据控件中,私有数据控件是一 个数据簇,与类库文件是一一对应的,并保存在类库文 件中,私有数据控件的名称以“.ctl”作为扩展名。
相关文档
最新文档