加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

组合子类型(Scala)

发布时间:2020-12-16 09:23:23 所属栏目:安全 来源:网络整理
导读:我正在寻找一个干净的面向对象的方式来模拟以下内容(在Scala中): 一个人可以是: 某公司的经理 数学家 世界级网球运动员 爱好者程序员 当地学校的志愿者 创意画家 这表明我们介绍一个Person的超类和子类: 类经理 数学类 class TennisPlayer 类HobbyistProg
我正在寻找一个干净的面向对象的方式来模拟以下内容(在Scala中):

一个人可以是:

>某公司的经理
>数学家
>世界级网球运动员
>爱好者程序员
>当地学校的志愿者
>创意画家

这表明我们介绍一个Person的超类和子类:

>类经理
>数学类
> class TennisPlayer
>类HobbyistProgrammer
>班志愿者
>类画家

Manager类具有以下方法:getSalary(),workLongHours(),findNewJob()等.TennisPlayer类具有以下方法:getWorldRanking(),playGame(),strainAnkle()等等.另外还有类Person中的方法,如getsSick().一个有病的经理失去了工作,网球运动员在赛季停止了运动.

此外,课程是不可变的.也就是说,例如,strainAnkle()返回一个新的TennisPlayer,它具有紧张的脚踝,但是所有其他属性保持不变.

现在的问题是:我们如何模拟一个人既可以是管理者又可以是TennisPlayer,

重要的是,该解决方案既保持了不变性,又保证了安全性.

我们可以实现类:

>经理和数学家
> ManagerAndTennisPlayerAndPainter
>经理和画家

但这导致班级的组合爆炸.

我们还可以使用traits(with state),但是我们如何实现诸如findNewJob()之类的方法,这些方法需要返回一个具有相同特征的新人,而且具有新的Manager特征状态.同样,我们如何实现诸如getsSick()的方法?

问题:您将如何在Scala的干净OO时尚中实现?记住:不可变性和类型安全是必须的.

解决方法

这不像我继承的理想情况.也许你试图强制将事情变成继承模式,因为处理具有不变值的组合似乎很尴尬.这是几种方法之一.

object Example {
  abstract class Person(val name: String) {
    def occupation: Occupation
    implicit val self = this
    abstract class Occupation(implicit val practitioner: Person) {
       def title: String
       def advanceCareer: Person
    }
    class Programmer extends Occupation {
      def title = "Code Monkey"
      def advanceCareer = practitioner
    }
    class Student extends Occupation {
      def title = "Undecided"
      def advanceCareer = new Person(practitioner.name) {
        def occupation = new Programmer
      }
    }
  }

  def main(args: Array[String]) {
    val p = new Person("John Doe") { def occupation = new Student }
    val q = p.occupation.advanceCareer
    val r = q.occupation.advanceCareer
    println(p.name + " is a " + p.occupation.title)
    println(q.name + " is a " + q.occupation.title)
    println(r.name + " is a " + r.occupation.title)
    println("I am myself: " + (r eq r.occupation.practitioner))
  }
}

让我们试试吧

scala> Example.main(Array())
John Doe is a Undecided
John Doe is a Code Monkey
John Doe is a Code Monkey
I am myself: true

所以这样做有点有用.

这里的诀窍是,每当一个职业(这是一个内在类)决定改变事情时,你创建你的人的匿名子类.它的工作是创造一个新角色,新角色完整无缺;这是通过隐含的val self = this和对职业的隐式构造函数来帮助的,这有助于自动加载人的正确实例.

您可能需要一个职业列表,因此可能会需要帮助方法来重新生成专业列表.就像是

object Example {
  abstract class Person(val name: String) {
    def occupations: List[Occupation]
    implicit val self = this
    def withOccupations(others: List[Person#Occupation]) = new Person(self.name) {
      def occupations = others.collect {
        case p: Person#Programmer => new Programmer
        case s: Person#Pirate => new Pirate
      }
    }
    abstract class Occupation(implicit val practitioner: Person) {
       def title: String
       def addCareer: Person
       override def toString = title
    }
    class Programmer extends Occupation {
      def title = "Code Monkey"
      def addCareer: Person = withOccupations( this :: self.occupations )
    }
    class Pirate extends Occupation {
      def title = "Sea Monkey"
      def addCareer: Person = withOccupations( this :: self.occupations )
    }
  }

  def main(args: Array[String]) {
    val p = new Person("John Doe") { def occupations = Nil }
    val q = (new p.Programmer).addCareer
    val r = (new q.Pirate).addCareer
    println(p.name + " has jobs " + p.occupations)
    println(q.name + " has jobs " + q.occupations)
    println(r.name + " has jobs " + r.occupations)
    println("I am myself: " + (r eq r.occupations.head.practitioner))
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读