`
lw9956164
  • 浏览: 27211 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
最近访客 更多访客>>
社区版块
存档分类
最新评论

实现继承(代码学习第五天)

阅读更多
近十几年来,面向对象语言设计的要素一直是继承的核心。不支持继承的语言(如 Visual Basic)被嘲讽是 “玩具语言” ,不适合真正的工作。与此同时,支持继承的语言所采用的支持方法五花八门,导致了许多争论。多重继承是否真的必不可少(就像 C++ 的创作者认定的那样),它是否不必要而丑陋的(就像 C# 和 Java 的创作者坚信的那样)?Ruby 和 Scala 是两种较新的语言,采取了多重继承的这种方法 — 正如我在上期介绍 Scala 的特征时所讨论的那样(参见 参考资料)。

关于本系列Ted Neward 将和您一起深入探讨 Scala 编程语言。在这个新的 developerWorks 系列 中,您将深入了解 Sacla,并在实践中看到 Scala 的语言功能。进行比较时,Scala 代码和 Java 代码将放在一起展示,但(您将发现)Scala 中的许多内容与您在 Java 编程中发现的任何内容都没有直接关联,而这正是 Scala 的魅力所在!如果用 Java 代码就能够实现的话,又何必再学习 Scala 呢?
.与所有 杰出的语言一样,Scala 也支持实现继承(参见 参考资料)。在 Java 语言中,单一实现继承模型允许您扩展基类,添加新方法和字段等。尽管存在某些句法变更,Scala 的实现继承依然类似于 Java 语言中的实现。不同的是 Scala 融合了对象和函数语言设计,这非常值得我们在本期文章中进行讨论。

普通 Scala 对象

与本系列之前的文章类似,我将使用 Person 类作为起点,探索 Scala 的继承系统。清单 1 展示了 Person 的类定义:


清单 1. 嘿,我是人类

// This is Scala
class Person(val firstName:String, val lastName:String, val age:Int)
{
  def toString = "[Person: firstName="+firstName+" lastName="+lastName+
                         " age="+age+"]"
}
 


Person 是一个非常简单的 POSO(普通 Scala 对象,Plain Old Scala Object),具有三个只读字段。您可能会想起,要使这些字段可以读写,只需将主构造函数声明中的 val 更改为 var 即可

无论如何,使用 Person 类型也非常简单,如清单 2 所示:


清单 2. PersonApp

// This is Scala
object PersonApp
{
  def main(args : Array[String]) : Unit =
  {
    val bindi = new Person("Tabinda", "Khan", 38)
    System.out.println(bindi)
  }
}




这算不上什么令人惊讶的代码,但给我们提供了一个起点。


--------------------------------------------------------------------------------
回页首
Scala 中的抽象方法

随着该系统的发展,越来越明显地意识到 Person 类缺乏一个成为 Person 的重要部分,这个部分是做些事情 的行为。许多人都会根据我们在生活中的作为来定义自己,而不是根据现有和占用的空间。因此,我会添加一个新方法,如清单 3 所示,这赋予了 Person 一些意义:


清单 3. 很好,做些事情!

// This is Scala
class Person(val firstName:String, val lastName:String, val age:Int)
{
  override def toString = "[Person: firstName="+firstName+" lastName="+lastName+
                          " age="+age+"]"

  def doSomething = // uh.... what?
}



这带来了一个问题:Person 的用途究竟是什么?有些 Person 绘画,有些唱歌,有些编写代码,有些玩视频游戏,有些什么也不做(问问十几岁青少年的父母)。因此,我会为 Person 创建 子类,而不是尝试去将这些活动直接整合到 Person 本身之中,如清单 4 所示:


清单 4. 这个人做的事情很少

// This is Scala
class Person(val firstName:String, val lastName:String, val age:Int)
{
  override def toString = "[Person: firstName="+firstName+" lastName="+lastName+
                          " age="+age+"]"

  def doSomething = // uh.... what?
}

class Student(firstName:String, lastName:String, age:Int)
  extends Person(firstName, lastName, age)
{
  def doSomething =
  {
    System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")
  }
}



当尝试编译代码时,我发现无法编译。这是因为 Person.doSomething 方法的定义无法工作;这个方法需要一个完整的主体(或许可抛出异常来表示它应在继承类中被覆盖),或者不需要主体,类似于 Java 代码中抽象方法的工作方式。我在清单 5 中尝试使用抽象的方法:


清单 5. 抽象类 Person

// This is Scala
abstract class Person(val firstName:String, val lastName:String, val age:Int)
{
  override def toString = "[Person: firstName="+firstName+" lastName="+lastName+
                          " age="+age+"]"

  def doSomething; // note the semicolon, which is still optional
                   // but stylistically I like having it here
}

class Student(firstName:String, lastName:String, age:Int)
  extends Person(firstName, lastName, age)
{
  def doSomething =
  {
    System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")
  }
}




请注意,我如何使用 abstract 关键字装饰 Person 类。abstract 为编译器指出,是的,这个类应该是抽象的。在这方面,Scala 与 Java 语言没有区别。

对象,遇到函数

由于 Scala 融合了对象和函数语言风格,我实际上建模了 Person(如上所述),但并未创建子类型。这有些古怪,但强调了 Scala 对于这两种设计风格的整合,以及随之而来的有趣理念。

回忆 前几期文章,Scala 将函数作为值处理,就像处理语言中的其他值一样,例如 Int、Float 或 Double。在建模 Person 时,我可以利用这一点来获得 doSomething,不仅将其作为一种继承类中覆盖的方法,还将其作为可调用、替换、扩展的 函数值。清单 6 展示了这种方法:


清单 6. 努力工作的人

// This is Scala   
class Person(val firstName:String, val lastName:String, val age:Int)
{
  var doSomething : (Person) => Unit = 
    (p:Person) => System.out.println("I'm " + p + " and I don't do anything yet!");
    
  def work() =
    doSomething(this)
    
  override def toString = "[Person: firstName="+firstName+" lastName="+lastName+
                          " age="+age+"]"
}

object App
{
  def main(args : Array[String]) =
  {
    val bindi = new Person("Tabinda", "Khan", 38)
    System.out.println(bindi)
    
    bindi.work()
    
    bindi.doSomething =
      (p:Person) => System.out.println("I edit textbooks")
      
    bindi.work()
    
    bindi.doSomething =
      (p:Person) => System.out.println("I write HTML books")
      
    bindi.work()
  }
}



将函数作为第一建模工具是 Ruby、Groovy 和 ECMAScript(也就是 JavaScript)等动态语言以及许多函数语言的常用技巧。尽管其他语言也可以用函数作为建模工具,(C++ 通过函数指针和/或成员函数指针实现,Java 代码中通过接口引用的匿名内部类实现),但所需的工作比 Scala(以及 Ruby、Groovy、ECMAScript 和其他语言)多得多。这是函数语言使用的 “高阶函数” 概念的扩展。(关于高阶函数的更多内容,请参见 参考资料。)

多亏 Scala 将函数视为值,这样您就可以在运行时需要切换功能的时候利用函数值。可将这种方法视为角色模式 —— Gang of Four 战略模式的一种变体,在这种模式中,对象角色(例如 Person 的当前就职状态)作为运行时值得到了更好的表现,比静态类型的层次结构更好。


--------------------------------------------------------------------------------
回页首
层次结构上层的构造函数

回忆一下编写 Java 代码的日子,有时继承类需要从构造函数传递参数至基类构造函数,从而使基类字段能够初始化。在 Scala 中,由于主构造函数出现在类声明中,不再是类的 “传统” 成员,因而将参数传递到基类将成为一个全新维度的问题。

在 Scala 中,主构造函数的参数在 class 行传递,但您也可以为这些参数使用 val 修饰符,以便在类本身上轻松引入读值器(对于 var,则为写值器)。

因此,清单 5 中的 Scala 类 Person 转变为清单 7 中的 Java 类,使用 javap 查看:


清单 7. 请翻译一下

// This is javap
C:\Projects\scala-inheritance\code>javap -classpath classes Person
Compiled from "person.scala"
public abstract class Person extends java.lang.Object implements scala.ScalaObje
ct{
    public Person(java.lang.String, java.lang.String, int);
    public java.lang.String toString();
    public abstract void doSomething();
    public int age();
    public java.lang.String lastName();
    public java.lang.String firstName();
    public int $tag();
}    



JVM 的基本规则依然有效:Person 的继承类在构造时向基类传递某些内容,而不管语言强调的是什么。(实际上,这并非完全 正确,但在语言尝试规避此规则时,JVM 会表现失常,因此大多数语言仍然坚持通过某种方法为其提供支持。)当然,Scala 需要坚守此规则,因为它不仅需要保持 JVM 正常运作,而且还要保持 Java 基类正常运作。这也就是说,无论如何,Scala 必须实现一种语法,允许继承类调用基类,同时保留允许我们在基类上引入读值器和写值器的语法。

为了将此放到更具体的上下文中,假设我通过以下方式编写了 清单 5 中的 Student 类:


清单 8. 坏学生!

// This is Scala
// This WILL NOT compile
class Student(val firstName:String, val lastName:String, val age:Int)
  extends Person(firstName, lastName, age)
{
  def doSomething =
  {
    System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")
  }
}
 


本例中的编译器将运行很长一段时间,因为我尝试为 Student 类引入一组新方法(firstName、lastName 和 age)。这些方法将与 Person 类上名称类似的方法彼此冲突,Scala 编译器不一定了解我是否正在尝试覆盖基类方法(这很糟糕,因为我可以在这些基类方法后隐藏实现和字段),或者引入相同名称的新方法(这也很糟糕,因为我可以在这些基类方法后隐藏实现和字段)。简而言之,您将看到如何成功覆盖来自基类的方法,但那并不是我们目前要追求的目标。

您还应注意到,在 Scala 中,Person 构造函数的参数不必一对一地与传递给 Student 的参数联系起来;这里的规则实际上与 Java 构造函数的规则完全相同。我们这样做只是为了便于阅读。同样,Student 可要求额外的构造函数参数,与在 Java 语言中一样,如清单 9 所示:


清单 9. 苛求的学生!

// This is Scala
class Student(firstName:String, lastName:String, age:Int, val subject:String)
  extends Person(firstName, lastName, age)
{
  def doSomething =
  {
    System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")
  }
}



您又一次看到了 Scala 代码与 Java 代码有多么的相似,至少涉及继承和类关系时是这样。


--------------------------------------------------------------------------------
回页首
语法差异

至此,您可能会对语法的细节感到迷惑。毕竟 Scala 并未像 Java 语言那样将字段与方法区分开来。这实际上是一项深思熟虑的设计决策,允许 Scala 程序员轻而易举地向使用基类的用户 “隐藏” 字段和方法之间的差异。考虑清单 10:


清单 10. 我是什么?

// This is Scala
abstract class Person(val firstName:String, val lastName:String, val age:Int)
{
  def doSomething
  
  def weight : Int
    
  override def toString = "[Person: firstName="+firstName+" lastName="+lastName+
                          " age="+age+"]"
}

class Student(firstName:String, lastName:String, age:Int, val subject:String)
  extends Person(firstName, lastName, age)
{
  def weight : Int =
    age // students are notoriously skinny

  def doSomething =
  {
    System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")
  }
}

class Employee(firstName:String, lastName:String, age:Int)
  extends Person(firstName, lastName, age)
{
  val weight : Int = age * 4 // Employees are not skinny at all

  def doSomething =
  {
    System.out.println("I'm working hard, hon, I swear! (Pass the beer, guys!)")
  }
}



注意查看如何定义 weight 使其不带有任何参数并返回 Int。这是 “无参数方法”。因为它看上去与 Java 语言中的 “专有” 方法极其相似,Scala 实际上允许将 weight 定义为一种方法(如 Student 中所示),也允许将其定义为字段/存取器(如 Employee 中所示)。这种句法决策使您在抽象类继承的实现方面有一定的灵活性。请注意,在 Java 中,即便是在同一个类中,只有通过 get/set 方法来访问各字段时,才能获得类似的灵活性。不知道判断正确与否,但我认为只有少数 Java 程序员会用这种方式编写代码,因此不经常使用灵活性。此外,Scala 的方法可像处理公共成员一样轻松地处理隐藏/私有成员。


--------------------------------------------------------------------------------
回页首
从 @Override 到 override

继承类经常需要更改在其某个基类内定义的方法的行为;在 Java 代码中,我们通过为继承类添加相同名称、相同签名的新方法来处理这个问题。这种方法的缺点在于签名录入的错误或含糊不清可能会导致没有征兆的故障,这也就意味着代码可以编译,但在运行时无法正确完成操作。

为解决这个问题,Java 5 编译器引入了 @Override 注释。@Override 验证引入继承类的方法实际上已经覆盖了基类方法。在 Scala 中,override 已经成为语言的一部分,几乎可以忘记它会生成编译器错误。因而,继承 toString() 方法应如清单 11 所示:


清单 11. 这是继承的结果

// This is Scala
class Student(firstName:String, lastName:String, age:Int, val subject:String)
  extends Person(firstName, lastName, age)
{
  def weight : Int =
    age // students are notoriously skinny

  def doSomething =
  {
    System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")
  }
  
  override def toString = "[Student: firstName="+firstName+
                          " lastName="+lastName+" age="+age+
                          " subject="+subject+"]"
}



非常简单明了。


--------------------------------------------------------------------------------
回页首
敲定

当然,允许继承覆盖的反面就是采取措施防止它:基类需要禁止子类更改其基类行为,或禁止任何类型的继承类。在 Java 语言中,我们通过为方法应用修饰符 final 来实现这一点,确保它不会被覆盖。此外,也可以为类整体应用 final,防止继承。实现层次结构在 Scala 中的效果是相同的:我们可以向方法应用 final 来防止子类覆盖它,也可应用于类声明本身来防止继承。

牢记,所有这些关于 abstract、final 和 override 的讨论都同样适用于 “名字很有趣的方法”(Java 或 C# 或 C++ 程序员可能会这样称呼运算符),与应用于常规名称方法的效果相同。因此,我们常常会定义一个基类或特征,为数学函数设定某些预期(可以称之为 “Mathable”),这些函数定义抽象成员函数 “+”、“-”、“*” 和 “/”,另外还有其他一些应该支持的数学运算,例如 pow 或 abs。随后,其他程序员可创建其他类型 — 可能是一个 Matrix 类,实现或扩展 “Mathable”,定义一些成员,看上去就像 Scala 以开箱即用的方式提供的内置算术类型。


--------------------------------------------------------------------------------
回页首
差别在于……

如果 Scala 能够如此轻松地映射到 Java 继承模型(就像本文至此您看到的那样),就应该能够从 Java 语言继承 Scala 类,或反之。实际上,这必须 可行,因为 Scala 与其他编译为 Java 字节码的语言相似,必须生成继承自 java.lang.Object 的对象。请注意,Scala 类可能也要继承自其他内容,例如特征,因此实际继承的解析和代码生成的工作方式可能有所不同,但最终我们必须能够以某种形式继承 Java 基类。(切记,特征类似于有行为的接口,Scala 编译器将特征分成接口并将实现推入特征编译的目标类中,通过这种方式来使之运作。)

但结果表明,Scala 的类型层次结构与 Java 语言中的对应结构略有不同;从技术上来讲,所有 Scala 类继承的基类(包括 Int、Float、Double 和其他数字类型)都是 scala.Any 类型,这定义了一组核心方法,可在 Scala 内的任意类型上使用:==、!=、equals、hashCode、toString、isInstanceOf 和 asInstanceOf,大多数方法通过名称即可轻松理解。在这里,Scala 划分为两大分支,“原语类型” 继承自 scala.AnyVal;“类类型” 继承自 scala.AnyRe。(scala.ScalaObject 又继承自 scala.AnyRef。)

通常,这并不是您要直接去操心的方面,但在考虑跨两种语言的继承时,可能会带来某些非常有趣的副作用。例如,考虑清单 12 中的 ScalaJavaPerson:


清单 12. 混合!
// This is Scala
class ScalaJavaPerson(firstName:String, lastName:String, age:Int)
  extends JavaPerson(firstName, lastName, age)
{
  val weight : Int = age * 2 // Who knows what Scala/Java people weigh?

  override def toString = "[SJPerson: firstName="+firstName+
                          " lastName="+lastName+" age="+age+"]"
}
 


……它继承自 JavaPerson:


清单 13. 看起来是否眼熟?
// This is Java
public class JavaPerson
{
    public JavaPerson(String firstName, String lastName, int age)
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    
    public String getFirstName()
    {
        return this.firstName;
    }
    public void setFirstName(String value)
    {
        this.firstName = value;
    }
    
    public String getLastName()
    {
        return this.lastName;
    }
    public void setLastName(String value)
    {
        this.lastName = value;
    }
    
    public int getAge()
    {
        return this.age;
    }
    public void setAge(int value)
    {
        this.age = value;
    }
    
    public String toString()
    {
        return "[Person: firstName" + firstName + " lastName:" + lastName +
            " age:" + age + " ]";
    }
    
    private String firstName;
    private String lastName;
    private int age;
} 

在编译 ScalaJavaPerson 时,它将照常扩展 JavaPerson,但按照 Scala 的要求,它还会实现 ScalaObject 接口。并照例支持继承自 JavaPerson 的方法,因为 ScalaJavaPerson 是一种 Scala 类型,我们可以期望它支持 Any 引用的指派,根据 Scala 的规则:


清单 14. 使用 ScalaJavaPerson
// This is Scala   
    val richard = new ScalaJavaPerson("Richard", "Campbell", 45)
    System.out.println(richard)
    val host : Any = richard
    System.out.println(host)



但在 Scala 中创建 JavaPerson 并将其指派给 Any 引用时会发生什么?


清单 15. 使用 JavaPerson

// This is Scala    
    val carl = new JavaPerson("Carl", "Franklin", 35)
    System.out.println(carl)
    val host2 : Any = carl
    System.out.println(host2)
 

结果显示,这段代码如期编译并运行,因为 Scala 能确保 JavaPerson “做正确的事情”,这要归功于 Any 类型与 java.lang.Object 类型的相似性。实际上,几乎可以说,所有扩展 java.lang.Object 的内容都支持存储到 Any 引用之中。(存在一些极端情况,我听说过,但我自己还从未遇到过这样的极端情况。)

最终结果?出于实践的目的,我们可以跨 Java 语言和 Scala 混搭继承,而无需过分担心。(最大的麻烦将是试图了解如何覆盖 “名字很有趣的 Scala 方法”,例如 ^=!# 或类似方法。)


--------------------------------------------------------------------------------
回页首
结束语

在这周的文章中,我为您介绍了 Scala 代码和 Java 代码之间的高度相似性意味着 Java 开发人员可以轻松理解并使用 Scala 的继承模型。方法覆盖的工作方式相同,成员可见性的工作方式相同,还有更多相同的地方。对于 Scala 中的所有功能,继承或许与 Java 开发中的对应部分最为相似。惟一需要技巧的部分就是 Scala 语法,这有着明显的差异。

习惯两种语言中继承方法的相似之处和细微的差异,您就可以轻松编写您自己的 Java 程序的 Scala 实现。例如,考虑流行的 Java 基类和框架的 Scala 实现,如 JUnit、Servlets、Swing 或 SWT。实际上,Scala 团队已经提供了一个 Swing 应用程序,名为 OOPScala(参见 参考资料),它使用 JTable,通过相当少的几行代码(数量级远远低于传统 Java 的对应实现)提供了简单的电子表格功能。

因此,如果您想知道如何在您的生产代码中应用 Scala,就应该准备好迈出探索的第一步。考虑在 Scala 中编写下一个程序的一小部分。正如您在这期文章中所了解到的那样,从恰当的基类继承,采用与 Java 程序中相同的方式提供覆盖,您就不会遇到任何麻烦。
分享到:
评论

相关推荐

    《Python学习手册》示例代码.zip

    4. **模块和包**:学习导入和使用Python内置及第三方模块,了解如何创建自己的模块和包,以及如何组织项目结构。 5. **数据结构**:深入理解列表、元组、字典和集合,包括它们的创建、访问、修改和删除元素的方法,...

    我的博客中OC学习第四天的代码练习题

    在“我的博客中OC学习第四天的代码练习题”这个主题下,我们主要探讨的是Objective-C(简称OC)编程语言的学习实践。Objective-C是苹果公司为iOS和macOS平台开发应用的主要语言,它基于C语言并扩展了面向对象的功能...

    21天学通JavaScript(第5版)- 源代码

    总之,21天学通JavaScript(第5版)的源代码为学习者提供了一个实践平台,通过这些代码,你可以逐步建立起对JavaScript的理解,进而能够创建功能丰富的网页和应用。记得理论结合实践,不断试验和改进,这样才能在...

    21天学通Java6(第五版)含源代码和课后习题代码

    总之,《21天学通Java6(第五版)含源代码和课后习题代码》是一本全面且实用的Java初学者教程,它不仅讲解了Java 6的基础知识,还提供了大量的实例和练习,帮助读者快速掌握编程技能,并为后续更高级的Java学习打下...

    ACCP(转换)C#第五章上课示例代码.rar

    《ACCP(转换)C#第五章上课示例代码》是针对C#编程学习者的一个资源包,其中包含了在ACCP(Accelerated Certified Computer Professional)课程中C#第五章上部分的教学实例代码。这个压缩文件的核心内容是帮助学生...

    第四章示例代码

    在本节中,我们将深入探讨"第四章示例代码"所涵盖的IT知识。这个标题表明我们正在讨论一个与编程或软件开发相关的章节,其中包含了若干示例代码,可能来自于一本教程、课程或项目实践。代码是计算机科学的核心,它是...

    Python学习手册源代码

    5. **标准库和第三方库**:Python拥有丰富的标准库,如os、sys、numpy、pandas等,同时还有大量的第三方库,如requests(HTTP请求)、matplotlib(数据可视化)、scikit-learn(机器学习)。"LP4E-examples"可能涵盖...

    21天学通C++(第七版)源代码

    《21天学通C++》是一本广受欢迎的C++编程入门教程,其第七版提供了全面且深入的C++语言学习指导。本书旨在帮助初学者在21天内建立起坚实的C++编程基础,通过实践性的例子和练习,让读者快速掌握C++的核心概念和编程...

    学习javaEE第十五天练习代码Day15.rar

    本练习代码是针对学习JavaEE的第十五天内容,主要涵盖了以下几个重要的Java核心概念: 1. **多态中的父类作为返回值**:在面向对象编程中,多态是核心特性之一,允许我们使用父类型的引用指向子类型对象。这样做的...

    第一行代码Android学习练习代码3

    【标题】"第一行代码Android学习练习代码3" 涉及的是Android应用程序开发中的实践环节,主要聚焦在自定义视图(Custom Views)的创建和应用。Android平台提供了丰富的UI组件,但有时为了满足特定设计需求或实现独特...

    深度学习框架pytorch入门与实践源代码.rar

    《PyTorch深度学习入门与实践》源代码详解 PyTorch是Facebook开源的一个强大而灵活的深度学习框架,以其动态计算图模式和易于使用的特性受到了广大开发者和研究者的青睐。本篇将深入探讨PyTorch的核心概念、关键...

    C#书本第1章到第5章例题源代码.rar

    《C#书本第1章到第5章例题源代码》这个压缩包包含了C#编程语言的基础到进阶的学习实例,旨在帮助初学者和有经验的开发者更好地理解和掌握C#语言的核心概念与技巧。通过分析和实践这些源代码,读者可以深入理解C#的...

    21天学通C++(第六版)源代码

    5. **继承与多态**:继承允许一个类(子类)继承另一个类(父类)的属性和行为,实现代码重用。多态是指同一消息可以根据接收者的不同而表现出不同的行为,常通过虚函数和纯虚函数实现。 6. **模板**:C++的模板是...

    c# 21天学习的 第一届的源代码

    在C#编程语言的学习过程中,"C# 21天学习的 第一届的源代码"是一个非常有价值的资源,尤其适合初学者。这个压缩包包含了21天学习计划的源代码,通过逐步深入的实践项目,帮助学习者系统地理解和掌握C#的基础以及进阶...

    C#入门经典第五版源代码

    通过深入研究《C#入门经典第五版》的源代码,初学者可以逐步掌握C#编程的基本技能,并逐步提升至更高层次。实际的代码示例比理论更生动,更能帮助理解和应用编程概念。对于希望快速入门C#的小白来说,这是一个非常...

    C#入门经典(第五版)源代码

    《C#入门经典(第五版)》是一本深受程序员喜爱的C#学习书籍,其源代码是初学者和进阶者深入理解C#编程的重要参考资料。通过这些源代码,你可以直观地看到各种C#语法、面向对象编程概念、类库应用以及实际项目中的...

    c++ primer plus第五版源代码与编程心得

    总之,《C++ Primer Plus 第五版》的源代码与编程心得是学习C++的宝贵资源。通过阅读和实践,我们可以深化对C++语言的理解,提升编程技巧,并且吸取前人的经验教训,避免在编程旅程中走弯路。这本书不仅适合初学者,...

    ACCP5.0S2教程\使用Java实现面向对象编程(Java OOP)\使用Java实现面向对象编程(Java OOP)上机贯穿案例源码

    面向对象编程(Object-Oriented Programming,简称OOP)是一种重要的编程范式,它基于“对象”的概念,通过封装、继承和多态等核心特性,实现了代码的复用和模块化,提高了软件开发的效率和可维护性。在Java语言中,...

    JAVA程序设计实验代码(第八章)

    实验代码是学习和掌握这些概念的关键,因为它们提供了实际应用的例子。以下是根据标题和描述所涉及的一些重要知识点: 1. **面向对象编程**:Java是一种纯面向对象编程语言,第八章可能详细讲解类、对象、继承、...

    21天学通Java2(第三版)程序源代码

    《21天学通Java2(第三版)》是一本旨在帮助初学者快速掌握Java编程技术的书籍。这本书通过21天的学习计划,系统地介绍了Java语言的基础知识和实际应用,旨在让读者在短时间内能够独立编写Java程序。提供的程序源代码...

Global site tag (gtag.js) - Google Analytics