精华内容
下载资源
问答
  • 动态类型、静态类型和强类型、弱类型的区别
    千次阅读
    2018-08-24 20:23:47

    编程语言一般分为动态类型、静态类型和强类型、弱类型,例如Java是静态、强类型编程语言,而JavaScript是动态、弱类型编程语言。

    一、动态类型与静态类型

    动态类型语言

    运行期间才做数据类型检查的语言,即动态类型语言编程时,永远不用给任何变量指定数据类型。该语言会在第一次赋值给变量时,在内部将数据类型记录下来。例如:JavaScript、Python、PHP。

    优点:方便阅读,不需要写非常多的类型相关的代码;

    缺点:不方便调试,命名不规范时会造成读不懂,不利于理解等。

    静态类型语言

    编译期间做检查数据类型的语言,即写程序时要声明所有变量的数据类型,是固定的。使用数据之前,必须先声明数据类型(int ,float,double等)。相当于使用之前,首先要为它们分配好内存空间。

    例如:C/C++是静态类型语言的典型代表,其他的静态类型语言还有C#、JAVA等。

    优点:结构非常规范,便于调试,方便类型安全

    缺点:为此需要写更多类型相关代码,较复杂。

    二、强类型与弱类型

    强类型

    指的是程序中表达的任何对象所从属的类型都必须能在编译时刻确定。强类型是针对类型检查的严格程度而言的,它指任何变量在使用的时候必须要指定这个变量的类型,而且在程序的运行过程中这个变量只能存储这个类型的数据。因此,对于强类型语言,一个变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。例如:假设定义了一个double类型变量a,不经过强制类型转换那么程序int b = a是无法通过编译。常用的强类型语言有Java、C# 、Apex和Python等。

    强类型的优点:
    1、编译时刻能检查出错误的类型匹配,以提高程序的安全性;
    2、可以根据对象类型优化相应运算,以提高目标代码的质量;
    3、减少运行时刻的开销。

    弱类型

    正好与强类型相反,编译时的检查很弱,它仅能区分指令和数据,弱类型语言允许变量类型的隐式转换,允许强制类型转换等,如字符串和数值可以自动转化。

    二者区别:

    1、不管是强类型还是弱类型,变量都有两个属性:类型和值;即弱类型的变量同样有类型。不管是哪一种编程语言,其中使用的变量,都既有类型,又有值。强类型的变量类型,必须在源代码中明确定义,称之为“变量声明”,弱类型的变量类型则是无需声明的,由解释器解释。但是,这并不意味着,弱类型的变量就没有类型这一概念了。

    2、强类型的变量类型是不能改变的,弱类型变量是随需改变的,这是强弱的真正含义。 强类型的变量一经声明,就只能存储这种类型的值,其他的值则必须通过转换之后才能赋给该变量,有编译器自动理解的转换,也有由程序员明确指定的强制转换。但是,弱类型的变量类型则是随着需要不断转换。

    3、强制转换并没有改变变量类型。强类型语言有个“强制转换”,这改变的是变量的值的类型,以便进行赋值,而没有改变变量的类型。变量的类型是不允许改变的。

    更多相关内容
  • C#中的动态类型(Dynamic)

    千次阅读 2022-02-25 14:36:35
    一、动态类型简介 .NET 4 中引入了动态类型。动态对象(dynamic)使您可以处理诸如 JSON 文档之类的结构内容,这些结构的组成可能要到运行时才能知道【该类型是一种静态类型,但类型为dynamic的对象会跳过静态类型...

    一、动态类型简介

         .NET 4 中引入了动态类型。动态对象(dynamicObject)使您可以处理诸如 JSON 文档之类的结构内容,这些结构的组成可能要到运行时才能知道【 该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查。 大多数情况下,该对象就像具有类型 object 一样。 在编译时,将假定类型化为 dynamic 的元素支持任何操作。 因此,不必考虑对象是从 COM API、从动态语言(例如 IronPython)、从 HTML 文档对象模型 (DOM)、从反射还是从程序中的其他位置获取自己的值。 但是,如果代码无效,则在运行时会捕获到错误。

         .NET 4.0 中引入的 dynamic 关键字为 C# 编程带来了一个范式转变。对于 C# 程序员来说,强类型系统之上的动态行为可能会让人感到不适 —— 当您在编译过程中失去类型安全性时,这似乎是一种倒退。【动态编程可能使您面临运行时错误。声明一个在执行过程中会发生变化的动态变量是可怕的,当开发人员对数据做出错误的假设时,代码质量就会受到影响】。

       对 C# 程序员来说,避免代码中的动态行为是合乎逻辑的,具有强类型的经典方法有很多好处。通过类型检查得到的数据类型的良好反馈对于正常运行的程序是至关重要的,一个好的类型系统可以更好地表达意图并减少代码中的歧义。

        随着动态语言运行时(Dynamic Language Runtime,DLR)的引入,这对 C# 意味着什么呢? .NET 提供了丰富的类型系统,可用于编写企业级软件。让我们来仔细看看 dynamic 关键字,并探索一下它的功能。

    二、类型层次结构

    C#中的动态类型(Dynamic)的项目工程icon-default.png?t=M1L8https://download.csdn.net/download/xiaochenXIHUA/82343997    公共语言运行时(Common Language Runtime,CLR)中的每种类型都继自 System.Object,【这意味着 object 类型是整个类型系统的公共父类】。当我们研究更神奇的动态行为时,这一事实本身就能为我们提供帮助。这里的想法是开发这种“代码感”,以便于您了解如何驾驭 C# 中的动态类型。

      C#的基础数据类型继承自ValueType;而ValueType 重写来自 object 类的默认行为。ValueType 的子类在栈(stack)上运行,它们的生命周期较短,效率更高。而string则是派生自object。

    以下为演示程序:

            //1-基础类型 是否继承 ValueType
            private static void BaseTypeInheritValueType<T>()
            {
                string str = $"{typeof(T).Name}\t继承于 ValueType:{typeof(T).IsSubclassOf(typeof(ValueType))}";
    
                Print(str);
            }
    
    
            //2-ValueType 是否继承 System.Object
            private static void ValueTypeInheritObject()
            {
                string str = $"ValueType 继承于 System.Object:{typeof(ValueType).IsSubclassOf(typeof(System.Object))}";
    
                Print(str);
            }
    
    
            //3-string 是否继承 System.Object
            private static void StringInheritObject()
            {
                string str = $"string 继承于 System.Object:{typeof(string).IsSubclassOf(typeof(System.Object))}";
    
                Print(str);
            }
                //1-byte 是否继承 ValueType
                BaseTypeInheritValueType<byte>();
                //1-short 是否继承 ValueType
                BaseTypeInheritValueType<short>();
                //1-int 是否继承 ValueType
                BaseTypeInheritValueType<int>();
                //2-uint 是否继承 ValueType
                BaseTypeInheritValueType<uint>();
                //1-Long 是否继承 ValueType
                BaseTypeInheritValueType<long>();
                //1-float 是否继承 ValueType
                BaseTypeInheritValueType<float>();
                //1-double 是否继承 ValueType
                BaseTypeInheritValueType<double>();
                //1-bool 是否继承 ValueType
                BaseTypeInheritValueType<bool>();
                //1-Enum 是否继承 ValueType
                BaseTypeInheritValueType<Enum>();
                //1-char 是否继承 ValueType
                BaseTypeInheritValueType<char>();
                //1-string 是否继承 ValueType
                BaseTypeInheritValueType<string>();

     值类型和引用类型都是 CLR 的基本构建块,这种优雅的类型系统在 .NET 4.0 和动态类型之前就有了。如下是公共语言运行时(CLR) 的类型系统:

    三、动态语言运行时

    3.1、动态语言运行时基础

        动态语言运行时(Dynamic Language Runtime, DLR)是处理动态对象的一种便捷方法。比如:您有 XML 或 JSON 格式的数据,但是数据其中的成员你并不知道。此时DLR 允许您使用自然代码来处理对象和访问成员。

        对于 C#,这使您可以处理在编译时不知道其类型的库。动态类型消除了自然 API 代码中的万能字符串。这就开启了像 IronPython 一样位于 CLR 之上的动态语言。

    可以将 DLR 视为支持三项主要服务:

    动态语言运行时的三项主要服务
    序号内容说明
    1表达式树表达式树,来自 System.Linq.Expressions 命名空间。编译器在运行时生成具有动态语言互操作性的表达式树
    2调用站点缓存调用站点缓存,即缓存动态操作的结果。DLR 缓存像 a + b 之类的操作,并存储 a 和 b 的特征。当执行动态操作时,DLR 将检索先前操作中可用的信息。
    3动态对象互操作性是可用于访问 DLR 的 C# 类型动态对象互操作性是可用于访问 DLR 的 C# 类型。这些类型包括 DynamicObject 和 ExpandoObject。可用的类型还有很多

    DLR 和 CLR 的结合图如下:

    每种类型都是从 System.Object 派生而来的。嗯,这句话对于 CLR 是适用的,但是对于 DLR 呢? 

    示例代码如下:

            //4-测试DLR 是否继承 System.Object
            private static void DLRObjectInheritObject<T>()
            {
                string str = $"{typeof(T).Name}\t继承于 System.Object:{typeof(T).IsSubclassOf(typeof(System.Object))}";
    
                Print(str);
            }
                //4-测试DynamicObject 是否继承 System.Object
                DLRObjectInheritObject<System.Dynamic.DynamicObject>();
                //4-测试ExpandoObject 是否继承 System.Object
                DLRObjectInheritObject<System.Dynamic.ExpandoObject>();

    运行结果如下:

     3.2、动态语言运行时应用场景

        动态类型解决的一个问题是,当您有一个不知道其成员的 JSON HTTP 请求时,假设要在 C# 中使用此任意的 JSON。要解决这个问题,请将此 JSON 序列化为 C# 动态类型。

    我将使用 Newtonsoft 序列化库,您可以通过 NuGet 添加此依赖项。

        您可以使用这个序列化程序来处理 ExpandoObject 和 DynamicObject。探索每种动态类型给动态编程带来了什么。

    3.3、ExpandoObject 动态类型

      【ExpandoObject是一种方便的类型,允许设置和检索动态成员。它实现了 IDynamicMetaObjectProvider,该接口允许在 DLR 中的语言之间共享实例。因为它实现了 IDictionary 和 IEnumerable,所以它也可以处理 CLR 中的类型。

        举例来说,它允许将 ExpandoObject 的实例转换为 IDictionary,然后像其它任意的 IDictionary 类型一样枚举成员。

    要用 ExpandoObject 处理任意 JSON,您可以编写以下程序:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Test_Dynamic
    {
        class PeopleInfo
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public string Sex { get; set; }
            public int Age { get; set; }
            public string TelNumber { get; set; }
            public string Address { get; set; }
    
    
        }//Class_end
    
    }
            //获取人员信息
            private static PeopleInfo GetPeopleInfo()
            {
                PeopleInfo peopleInfo = new PeopleInfo();
                peopleInfo.Id = Guid.NewGuid().ToString("N");
                peopleInfo.Name = "牛奶咖啡";
                peopleInfo.Sex = "男";
                peopleInfo.Age = 27;
                peopleInfo.TelNumber = "13115672345";
                peopleInfo.Address = "中华人民共和国测试省测试市测试街道测试号";
    
                return peopleInfo;
            }
    
            //将一个对象序列化为Json字符串
            private static string GetJsonStrOfObject<T>(T t)
            {
                string str = Newtonsoft.Json.JsonConvert.SerializeObject(t);
                return str;
    
            }
    
            //将一个Json字符串反序列化为动态类型(通过ExpandoObject类型)
            private static dynamic GetExpandoObjectResultOfJsonStr(string jsonStr)
            {
                if (string.IsNullOrEmpty(jsonStr)) return null;
    
                dynamic result = Newtonsoft.Json.JsonConvert.DeserializeObject<System.Dynamic.ExpandoObject>(jsonStr);
               
                return result;
            }
    
            //输出ExpandoObject类型的解析内容
            private static void PrintExpandoObjectInfo(dynamic dc)
            {
                string str = $"编号:{dc?.Id}\t姓名:{dc?.Name}\t性别:{dc?.Sex}\t年龄:{dc?.Age}\t" +
                    $"电话:{dc?.TelNumber}\t住址:{dc?.Address}";
    
                Print(str);
                
            }
    
            //输出ExpandoObject类型的解析内容(IDictionary)
            private static void PrintExpandoObjectInfo2(dynamic dc)
            {
                if (dc == null) return;
    
                foreach (var item in dc as System.Collections.Generic.IDictionary<string, object>??
                    new System.Collections.Generic.Dictionary<string, object>())
                {
                    string str=$"IDictionary={item.Key}:{item.Value}"; 
    
                    Print(str);
                }
            }

       调用方法示例如下:

           //5-ExpandoObject示例
            private static void ExpandoObjectSample()
            {
    
                //1-将一个PeopleInfo对象序列化为Json字符串
                string jsonStr = GetJsonStrOfObject(GetPeopleInfo());
    
                //2-将一个Json字符串反序列化为动态类型(通过ExpandoObject类型)
                dynamic dc = GetExpandoObjectResultOfJsonStr(jsonStr);
    
                //3-输出ExpandoObject类型的解析内容
                PrintExpandoObjectInfo(dc);
    
                //4-输出ExpandoObject类型的解析内容(IDictionary)
                PrintExpandoObjectInfo2(dc);
            }
    

    运行结果如下:

    请注意:尽管它是一个动态 JSON,但它会绑定到 CLR 中的 C# 类型。由于数字的类型未知,因此序列化程序默认会选择支持的最大类型(比如Age字段就使用的是long类型)。

        我们成功地将序列化结果转换成了具有 null 检查的 dynamic 类型,其原因是序列化程序返回来自 CLR的 object 类型。因为 ExpandoObject 继承自 System.Object,所以可以被拆箱成 DLR 类型。

        更奇妙的是,可以用 IDictionary 枚举 dynamic,如下图所示:

            //输出ExpandoObject类型的解析内容(IDictionary)
            private static void PrintExpandoObjectInfo2(dynamic dc)
            {
                if (dc == null) return;
    
                foreach (var item in dc as System.Collections.Generic.IDictionary<string, object>??
                    new System.Collections.Generic.Dictionary<string, object>())
                {
                    string str=$"IDictionary={item.Key}:{item.Value}"; 
    
                    Print(str);
                }
            }

    3.4、DynamicObject 动态类型

      【DynamicObject】 提供对动态类型的精确控制。您可以继承该类型并重写动态行为。例如:您可以定义如何设置和获取类型中的动态成员。DynamicObject 允许您通过重写选择实现哪些动态操作。这比实现 IDynamicMetaObjectProvider 的语言实现方式更易访问。它是一个抽象类,需要继承它而不是实例化它。该类有 14 个虚方法,它们定义了类型的动态操作,每个虚方法都允许重写以指定动态行为。

        假设您想要精确控制动态 JSON 中的内容。尽管事先不知道其属性,您却可以使用 DynamicObject 来控制类型。

    让我们来重写三个方法,TryGetMemberTrySetMember 和 GetDynamicMemberNames

    using System;
    using System.Collections.Generic;
    using System.Dynamic;
    using System.Text;
    
    namespace Test_Dynamic
    {
        class OpcJsonOfDynamic<T>: System.Dynamic.DynamicObject
        {
            private readonly IDictionary<string, T> _objProperty;
    
            public OpcJsonOfDynamic()
            {
                _objProperty = new Dictionary<string,T>();
            }
    
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                T typeObj;
    
                if (_objProperty.TryGetValue(binder.Name,out typeObj))
                {
                    result = typeObj;
                    return true;
                }
    
                result = null;
    
                return false;
            }
    
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                if (value.GetType()!=typeof(T))
                {
                    return false;
                }
    
                _objProperty[binder.Name]=(T)value;
    
                return true;
            }
    
            public override IEnumerable<string> GetDynamicMemberNames()
            {
                return _objProperty.Keys;
            }
    
            public IDictionary<string, T> GetKeyValues()
            {
                return _objProperty;
            }
    
        }//Class_end
    
    }

     C# 泛型强类型 _objProperty 以泛型的方式驱动成员类型。这意味着其属性类型来自泛型类型 T。动态 JSON 成员位于字典中,并且仅存储泛型类型。此动态类型允许同一类型的同类成员集合。尽管它允许动态成员集,但您可以强类型其行为。假设您只关心任意 JSON 中的 string 类型:

            //获取人员信息
    
            private static PeopleInfo GetPeopleInfo()
            {
                PeopleInfo peopleInfo = new PeopleInfo();
                peopleInfo.Id = Guid.NewGuid().ToString("N");
                peopleInfo.Name = "牛奶咖啡";
                peopleInfo.Sex = "男";
                peopleInfo.Age = 27;
                peopleInfo.TelNumber = "13115672345";
                peopleInfo.Address = "中华人民共和国测试省测试市测试街道测试号";
    
                return peopleInfo;
            }
    
    
            //输出DynamicObject类型的内容
            private static void PrintDynamicObjectInfo(System.Dynamic.DynamicObject dc)
            {
                if (dc == null) return;
    
                if (dc is OpcJsonOfDynamic<string>)
                {
                    OpcJsonOfDynamic<string> opcJsonOfDynamic = (dc as OpcJsonOfDynamic<string>);
    
                    foreach (var item in opcJsonOfDynamic.GetKeyValues())
                    {
                        string str = $"键:{item.Key}\t值:{item.Value}";
                        Print(str);
                    }
                    
                }
            }

    调用方法示例如下:

            //6-DynamicObject示例
            private static void DynamicObjectSample()
            {
                //1-将一个PeopleInfo对象序列化为Json字符串
                string jsonStr = GetJsonStrOfObject(GetPeopleInfo());
    
                //2-通过Dynamic对象操作Json
                System.Dynamic.DynamicObject dcObj = Newtonsoft.Json.JsonConvert.DeserializeObject<OpcJsonOfDynamic<string>>(jsonStr);
    
                //3-输出dcObj内容
                PrintDynamicObjectInfo(dcObj);
    
            }

    运行结果如下:

    3.5、类型结果

    • CLR 和 DLR 中的所有类型都继承自 System.Object
    • DLR 是所有动态操作发生的地方
    • ExpandoObject 实现了 CLR 中诸如 IDictionary 的可枚举类型
    • DynamicObject 通过虚方法对动态类型进行精确控制

     四、参考文档

    Working with the Dynamic Type in C# - Simple Talk (red-gate.com)https://www.red-gate.com/simple-talk/development/dotnet-development/working-with-the-dynamic-type-in-c/使用类型 dynamic - C# 编程指南 | Microsoft Docshttps://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/types/using-type-dynamic

    展开全文
  • 静态类型和动态类型有什么区别?

    千次阅读 2019-07-01 14:30:25
    编程语言按照类型检查可以分为两大类:**静态类型 (Static Typing) **和 动态类型 (Dynamic Typing)。在现在比较流行的这些语言里,静态类型的代表人物有 Java、C/C++、Golang 等,动态类型有 Python、Ruby 等。 ...

    编程语言按照类型检查可以分为两大类:静态类型 (Static Typing)动态类型 (Dynamic Typing)。在现在比较流行的这些语言里,静态类型的代表人物有 Java、C/C++、Golang 等,动态类型有 Python、Ruby 等。

    静态类型和动态类型有什么区别呢?为什么在程序语言设计时要考虑是静态还是动态?在写代码时,Python 写起来简洁,效率高,可能100行 Java 的程序10行 Python 就能搞定,所以以前我觉得静态类型的语言有点太死板了,不如动态类型的。但是经过这段时间编程语言的学习,不能说一个比另一个好,个有所长吧。这篇文章从3个角度、6个方面对比静态类型和动态类型。

    为什么会有静态类型/动态类型的概念?

    程序都需要进行错误的检查。比如 3 / 0,这个程序会有错误,我们应该在什么时候进行检查呢?

    1. 在写程序时,只要编辑器里出现除以0,报错。
    2. 在编译时,如果检查到了除以0,报错。
    3. 在程序运行时,运行到了除以9,报错。
    4. 不报错,返回无穷大 (+inf.0)。

    不同的语言设计上会选择在这4个过程中不同时候去报错。静态类型和动态类型的区别在于什么时候报类型的错误?,比如说 3 / "a“,静态类型多是在编译时,动态类型多是在程序运行时。怎么报类型的错误呢?语言里会有类型检查的机制,类型检查的目的是避免程序发生一些事情

    编程语言在设计时,要考虑 什么程序要类型检查?怎么执行类型检查?。静态类型和动态类型是这两个问题不同回答的产物。

    从写代码的角度对比

    方便性 Convenience

    静态类型更好:静态类型比较方便,因为不用去检查 x 是不是 number,* 默认只能是 number。

    ; Racket
    (define (cube x) 
      (if (not (number? x)) 
          (error "bad arguments")
          (* x x x)))
    
    (* ML *)
    fun cube x = x * x * x
    

    动态类型更好:动态类型比较方便,因为一个函数可以根据需要返回不同的类型。静态类型却需要去构造一个新的数据类型才能实现。

    ; Racket
    (define (f y) (if (> y 0) (+ y y) "hi"))
      
      
    (* ML *)
    datatype t = Int of int | String of string
    fun f y = if y > 0 then Int(y+y) else String "hi"
    
    fun foo x = case f x of
    		Int i => Int.toString i
    	      | String s => s
    

    更早的发现错误 Catching bugs earlier

    静态类型在编译时就能发现类型上的错误,都不用写 tests,可以比动态类型更早的找到 bug。

    但是喜欢动态类型的人会说,静态类型只能找到"简单"的错误,还是需要写单元测试的,在写单元测试时,肯定就能发现这些"简单"的错误了。

    性能 Performance

    静态类型的程序在运行时更快,因为在编译时已经进行了检测,不需要去储存和检测类型,可以节省程序运行的时间和空间。

    但是喜欢动态类型的人会说,动态类型在性能很关键的部分,可以有一些办法去优化类型的储存和检测,比如说 (let ([x (+ y y)]) (* x 4)),有两个 y,可以只检测一个,4 是一个整数,不需要检测,x 是 y + y 的结果,所以后面的那个 x 也可以不用检测。通过这些方式可以对程序进行一些优化,而不需要像静态类型一样要受到各种类型的限制。

    代码重用 Code Reuse

    动态类型更好:动态类型代码重用率更高,因为没有严格的类型系统,代码可以被不同类型的数据重用。一个最简单的例子

    # Ruby
    def double x
    	x + x
    end
    

    x 可以是数字,把数字翻倍。x 可以是 string,把两个 string 连在一起。

    动态类型中一个 list 里可以有不同的类型的数据,在循环遍历时会,能重用更多代码。

    静态类型更好:静态类型也有代码重用的很多方法,比如泛型,子类型等等。而且一个 list 只有一种类型的数据,可以避免一些难找的bug,也可以避免因为类型自由而滥用一些库。

    原型开发 Prototyping

    动态类型更好:动态类型更适合原型开发,因为在 Prototyping 时,不一定知道确切的数据结构和函数,类型上的自由可以不用在做原型时就确定数据结构,导致了要一直不断的去满足类型的检查,降低了原型开发的效率。

    静态类型更好:虽然效率上不一定比的上动态类型,静态类型能更好的记录整个系统在 Prototyping 的过程中,可以知道整个过程数据类型、数据结构是怎么变化的。如果是跟之前完全不相关的代码,可以直接重写,不需要在之前的做更改。在之前代码不确定的地方,可以用一些表示所有其他类型的方法,比如 | _ => raise Unimplemented

    再开发和维护 Evolution & Maintaince

    动态类型更好:在更改代码时,可以把代码能接受的变得更"宽",比如说修改函数返回类型,调用的代码如果对返回类型没有问题,可以不用更改。静态类型必须要更改所有调用的代码,不能进行局部的测试。

    静态类型更好:动态类型的不用更改旧代码是一个隐患,坊间流传动态类型是「写时一时爽,重构火葬场」,静态类型的类型检查会列出所有需要更改的地方,可以避免一些隐藏的bug。

    总结

    经过这些对比,可以看出静态类型和动态类型各有所长,不能简单粗暴的说一种比另外一种更好。个人而言,我觉得动态类型更适合比较小的程序,像 Python,Ruby,做为脚本语言,能简单快速的写完对文件的处理等。动态类型 Java 和 C++ 则能过支持大型的软件工程项目。

    当然具体选择静态类型或者动态类型,取决于想要什么时候做类型检查?想要什么样的语言特性,并且应该知道选择的 trade-off 是什么样的。

    Reference

    Coursera Programming Languages, Part B Week 3

    展开全文
  • C++动态类型与静态类型

    千次阅读 多人点赞 2017-07-21 15:00:45
    大多数情况下对象的静态类型和动态类型相同,我们不用关系二者区别;只有多态情况下,即在有虚函数的继承体系中,通过基类的指针或引用调用虚函数时,这时我们就需要关系指针或引用对象的动态类型,因为它们的静态...

    一、前言

        其实关于C++的动态绑定就足以写好多篇博客了,但在这篇文章中我不准备深刻剖析C++动态绑定机制(即虚函数机制),只是说明动态绑定和静态绑定的区别,强调C++对象的动态类型和静态类型。


    二、静态类型与动态类型

        什么是静态类型?什么是动态类型?首先这两种肯定是对象(变量)类型的一种说法,而区分这两种类型最直接的方法就是看表达式的形式。关于一个表达式的对象(变量)的静态类型和动态类型需要从两点进行分析:

            (1)该对象(变量)的静态类型和动态类型是否相等;

            (2)如果该对象的静态类型和动态类型不相等,其动态类型是否有作用。

    对于第(1)点,其实我们可以认为每个对象(变量)都存在动态类型和静态类型,只是大多数情况下一个对象的动态类型和静态类型是相等的,所以我们平常都没有强化这两个概念,如表达式int a; 对象a的静态类型和动态类型就是相等的,所以平常我们都是直接称呼变量a的类型是int。对于第(2)点,首先只有当我们的表达式使用的是指针或引用时对象的静态类型和动态类型才有可能不同,而且就算一个对象的静态类型和动态类型不相等,其还不一定能享受到动态类型所带来的方便(即动态绑定),因为我们知道,动态绑定的前提条件是继承体系中的子类继承并重写了基类的虚函数。

        如果觉得上面的解释有点绕,直接解释静态类型和动态类型的定义,一个对象(变量)的静态类型就是其声明类型,如表达式int a中的int就是对象a的声明类型,即静态类型;而一个对象(变量)的动态类型就是指程序执行过程中对象(指针或引用)实际所指对象的类型,如Base* pB = new Drived; 其中class Drived继承于class Base,则指针对象pB的静态类型就是Base(声明类型),动态类型就是Drived(实际所指对象的类型),又如Base* pB = new Base;此时指针对象pB的静态类型和动态类型也是相等的,都是Base。


    三、动态类型的作用

        上面已经说明了,大多数情况下一个对象的静态类型和动态类型都是相等的,而且就算其静态类型和动态类型不相等,也不一定会使动态类型发挥威力,那到底什么时候一个对象(变量)的动态类型能发挥其威力呢?三个条件:(1)该对象是指针或引用形式;(2)该对象的静态与动态类型不同;(3)应用场景为带虚函数的继承体系结构。其实你可以直接理解为:动态类型就是为动态绑定(C++继承的多态)准备的。只有当上述3个条件都满足了,动态类型才能发挥其威力,即很好的支持虚函数动态绑定机制,为什么呢?这与C++编译器对多态继承结构中的成员函数调用机制有关。

        假设有以下继承结构:class Drived : public Base,然后有表达式p->mem()或obj.mem(),其中mem()是一个类成员函数,但具体是基类还是子类,现在可以不用管,而且我们也不用管p或者obj是指向哪个类。当程序的编译期,当编译器遇到表达式p->mem()或obj.mem(),执行以下步骤:

            (1)首先确定p(或obj)的静态类型,即声明类型;

            (2)然后在p(或obj)的静态类型中查找mem()函数,如果没有找到,按照作用域规则,这时编译器会到其直接基类中寻找,并依次向上,直到达到继承链的顶端,如果在这个过程中找到了,则继续下一步,如果没有找到,则报错;

            (3)一旦找到名字匹配的mem()函数,则编译器会根据mem()是否是虚函数,以及我们是通过指针或引用(如p)来调用mem()函数,还是通过类对象(如obj)来调用mem()函数,生成不同的代码。如果mem()是虚函数且是通过指针或引用调用(如p->mem()),编译器生成的代码会检查其动态类型,这就是动态绑定的过程,也就是说编译器生成的代码会直到运行期确定了动态类型才决定具体调用基类还是子类的虚函数mem();如果mem()不是虚函数且是通过对象调用(如obj.mem()),则编译器会产生一个常规的函数调用代码,可以直接确定调用哪一个mem()函数。


    四、总结

        对上面的介绍进行总结:大多数情况下对象的静态类型和动态类型相同,我们不用关系二者区别;只有多态情况下,即在有虚函数的继承体系中,通过基类的指针或引用调用虚函数时,这时我们就需要关系指针或引用对象的动态类型,因为它们的静态类型毋庸置疑是基类,但动态类型有可能是子类(其实也不是有可能,要想应用多态,其动态类型必须是子类),所以动态类型就是跟虚函数、多态、动态绑定息息相关的。

    展开全文
  • 动态类型 类型断言与type-switch 全部代码 截图 参考 动态类型 我们知道Go不像Python,变量可以没有类型。那么如果一个函数的参数需要兼容多个类型或是需要判断变量类型该如何做呢? 我们可以使用接口,上一...
  • 动态类型语言和静态类型语言

    千次阅读 2018-05-24 15:54:33
    https://www.cnblogs.com/liuning8023/p/4286044.html  动态类型语言和静态类型语言本文主要说明动态类型语言和静态类型语言。类型检查所进行的检验处理以及实行类型的约束,可发生在编译时期(静态检查)或运行...
  • 另外编程语言除了编译型和解释型,还有静态语言、动态语言、强类型语言、弱类型语言。那么每种语言类型是什么样子的呢,下面让我们来看看吧。  但是在此之前,我们需要先了解一下计算机原因的发展史,从低级语言到...
  • 静态语言: 变量的类型在编译之前就需要确定,在编译的时候需要先编译,将源码转换成目标代码,然后...动态语言:不需要直接指定变量类型,在解释的时候,转换为目标代码和运行程序一步到位,比如python。 比较: ...
  • C#中的动态类型dynamic

    千次阅读 2019-07-02 10:37:34
    1,动态类型dynamic最常见啊的使用就是在将json字符串接受下来,然后像操作是js操作json一样去处理数据,很轻盈的!废话不多说,上代码! var info = "{\"Account\":\"张三\",\"Pwd\":\"12323\"}"; //json字符串 ...
  • C++3种动态类型识别的方法

    千次阅读 2018-08-11 15:56:38
    一,什么是动态类型 基类指针所指对象的实际类型 基类指针是否可以强制类型转换为子类指针取决于动态类型! 二,方法 1,利用多态 必须从基类开始提供类型虚函数 所有的派生类都必须重写类型虚函数 每个派生...
  • JavaScript是一种动态类型的脚本语言

    千次阅读 2018-11-25 04:16:01
    JavaScript是一种动态类型的脚本语言;在1995年时,由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。 ...
  • 动态类型语言&动态语言

    千次阅读 2017-11-18 18:56:34
    动态语言 动态类型语言首先,这是两个不同的概念动态语言 dynamic programming language程序运行时,允许改变程序结构(例如引进新函数、删除旧函数)或变量类型。 从这个观点来看,Perl、Python、Ruby是动态语言,...
  • 动态类型与静态类型 静态类型  是指不需要考虑表达式的执行期语义,仅分析程序文本而决定的表达式类型。静态类型仅依赖于包含表达式的程序文本的形式,而在程序运行时不会改变。通俗的讲,就是上下文无关,在编译...
  • 静态类型和动态类型检查

    千次阅读 2015-11-06 10:38:17
    1、静态类型和动态类型 如果大家希望学好C++的话那请务必多学习一下c++内部的对象模型,前面有很多博客都是关于这方面的不过都不是自己写的(因为自己很懒)。 举个例子:类A,类B,如果B没有继承A那这就没...
  • 一般在使用泛型时使用 void main() { var a; a = 10; a = "Dart"; dynamic b = 20; b = "huangxiaoguo"; var list = new List&lt;dynamic&gt;(); list.add("... pr...
  • 静态类型与动态类型

    千次阅读 多人点赞 2015-06-18 10:05:50
    静态类型 & 动态类型
  • c++动态类型转换

    千次阅读 2016-11-03 14:54:25
    在项目中使用了QtPropertyBrowser作为属性浏览器。为了方便统一管理,将所有的属性项使用QtVariantProperty来设置。为了方便双向通信建立了两个映射: QMappropertyToId;...这与QMap中的类型不同,需要
  • Qt动态类型转换

    千次阅读 2017-07-25 16:49:35
    reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它。我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的。(这句话是C++编程思想中的原话...
  • 类型系统的一些概念,众说纷纭,使用上也比较乱。有些东西,甚至不好严格定义。以下算学术界的一种相对“严格”的说法。 1. 先定义一些基础概念 Program Errors trapped errors。导致程序终止执行,如除0,Java中...
  • 题图:Photo by Timo Wagner on Unsplash江湖有言:“动态类型一时爽,代码重构火葬场”,听起来有点耸人听闻,但也没有想象中的那么严重,因为 P...
  • Dynamic动态类型

    千次阅读 2019-03-05 13:06:47
    什么是动态类型 了解什么是动态类型首先我们了解静态类型,在我们平时定义一个int i=1就是静态类型,静态类型就是我们在没有编译的时候已经明确的知道他是一个int类型,动态语言是我们在运行时才会知道的类型。所以...
  • Java 8支持动态语言,看到了很酷的Lambda表达式,对一直以静态类型语言自居的Java,让人看到了Java虚拟机可以支持动态语言的目标。
  • C#的动态类型ExpandoObject和DynamicObject

    千次阅读 2017-04-24 20:01:40
    这个类和动态类型有关,这个类能做些什么? 学过javascript的都知道,javascript里面有动态属性这个说法,现在C#里面同样有,具体的做法如下: 在使用这个类型之前,需要引入命名空间using System.Dynamic;  
  • C++ 对象的静态类型与动态类型

    千次阅读 2014-12-04 14:19:10
    继承导致对象的指针和引用具有两种不同的类型: 静态类型 和 动态类型 。 静态类型 :指针或者是引用声明时的类型。 动态类型 :由他实际指向的类型确定。   class Base {   } class Derived:public ...
  • java静态类型与动态类型

    千次阅读 2017-06-13 09:51:13
    动态类型检查:在程序运行期间验证类型安全的过程; Java使用静态类型检查在编译期间分析程序,确保没有类型错误。基本的思想是不要让类型错误在运行期间发生。class A { A me() { return this; } public void ...
  • 动态类型语言&静态类型语言

    千次阅读 2017-04-14 16:41:56
    1.动态类型语言概念:意思就是类型的检查是在运行时做的表现:使用变量前不需要声明变量举例:JavaScript、Ruby、Python这些都属于动态类型语言2.静态类型语言概念:意思就是类型判断是在运行前做的(如编译阶段)...
  • 以前需要将一段json字符串转换为C#对象时,一般都是定义一个与之对应的实体类来接收。... C# 4.0 之后有了动态类型dynamic。用这个东西配合Json.net可以实现不用定义实体类的json转dynamic类型对象
  • 关于如题这几个概念,大部分人应该比较熟悉,但是我昏了好久,所以写下来加深印象。 1. 动态语言 ...除此之外如Ruby、Python等也都属于动态语言,而C、C++等语言则不属于动态语言。 而其实我们平时说
  • go的静态类型和动态类型

    万次阅读 2018-11-16 20:17:49
    t) } 结果出现编译错误:t.X undefined (type TaskIntf has no field or method X) 注意到, 对于t而言,静态类型是TaskIntf, 动态类型(运行时)是Task. 而在t.X = 1时,编译器会进行静态检查, 故编译错误。 那...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,757,914
精华内容 703,165
关键字:

动态类型

友情链接: NL_RBF.zip