scala自身类型 self-type 的作用

本文深入探讨Scala中的self-type概念,解析其如何解决特质混入时的类型约束问题,并通过示例展示self-type在实践中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

self type 作用通常为了分割大类到多个特质traits的。比如cake pattern蛋糕模式中会用到self type
官网解释如下:
 
 
self type

self type of a trait is the assumed type of this, the receiver, to be used within the trait. Any concrete class that mixes in the trait must ensure that its type conforms to the trait’s self type. The most common use of self types is for dividing a large class into several traits (as described in Chapter 29 of Programming in Scala.

 

 

 

 

 

例子在<<Programming in Scala>> 第29章 第4小节给出的例子代码如下

 

 

 

29.4 Splitting modules into traits
 
package quickanswer.chapter10
 
class Food(fn:String){
  var name:String=fn
}
 
class Recipe(var rn:String,var foodLst:List[Food],var desc:String){//食谱
 
}
 
trait FoodCategories {
  case class FoodCategory(name: String, foods: List[Food])
  def allCategories: List[FoodCategory]
}
 
 
trait SimpleFoods {
  object Pear extends Food("Pear")
  object Apple extends Food("Apple")
  def allFoods = List(Apple, Pear)
  def allCategories = Nil
}
 
abstract class Database extends FoodCategories {
  def allFoods: List[Food]
  def allRecipes: List[Recipe]
  def foodNamed(name: String) =
  allFoods.find(f => f.name == name)
}
 
object SimpleDatabase extends Database with SimpleFoods with SimpleRecipes
 
trait SimpleRecipes { // Does not compile
 // this: SimpleFoods =>   // 注释掉这句话会编译错误,因为 Apple, Pear 是定义在SimpleFoods 的
  object FruitSalad extends Recipe(
  "fruit salad",
  List(Apple, Pear), // Uh oh
  "Mix it all together."
  )
  def allRecipes = List(FruitSalad)
}
 
 
object SplittingModulesIntoTraits extends App {
 
}
 
代码解释
 
 

dividing a large class( SimpleDatabase ) into several traits  (SimpleFoods ,SimpleRecipes),而在 定义trait SimpleRecipes  中又需要SimpleFoods 中的内容, 但是编译器器并不知道   SimpleRecipes 是混入SimpleFoods 的,而  Apple, Pear 是定义在SimpleFoods中的的,所以编译会报错 ,    而通过self type 解决了这个问题

 
从技术上讲,self type 是一个表示this类型的假定的类型。从编程角度来说,self type 要求具体的类必须混入指定的特质,否则会报编译错误。 如过有一个trait 是混入在其他trait中的,则其他trait需要用假定的类型self type
 

当SimpleRecipes 添加 this: SimpleFoods =>   后,Pear会被暗中转化为this.Pear ,这样是安全的,因为任何混入SimpleRecipes 的具体类必须也要混入SimpleFoods  。这意味着Pear会是这个具体类的一个成员。混入SimpleRecipes 的抽象类和trait没哟这个限制,但是他们是不能通过new 实例化的。所哟this.Pear 是安全的

 
 
 

书本解释如下"

 
The problem here is that Pear is located in a different trait from the one that
uses it, so it is out of scope. The compiler has no idea that SimpleRecipes
is only ever mixed together with SimpleFoods.
There is a way you can tell this to the compiler, however. Scala provides
the self type for precisely this situation. Technically, a self type is an assumed
type for this whenever this is mentioned within the class. Pragmatically,
a self type specifies the requirements on any concrete class the trait is mixed
into. If you have a trait that is only ever used when mixed in with another
trait or traits, then you can specify that those other traits should be assumed.
In the present case, it is enough to specify a self type of SimpleFoods, as
shown in Listing 29.15:
 
trait SimpleRecipes {
this: SimpleFoods =>
object FruitSalad extends Recipe(
"fruit salad",
List(Apple, Pear), // Now Pear is in scope
"Mix it all together."
)
def allRecipes = List(FruitSalad)
}
Listing 29.15 · A SimpleRecipes trait with a self type.
 
Given the new self type, Pear is now available. Implicitly, the reference
to Pear is thought of as this.Pear. This is safe, because any concrete
class that mixes in SimpleRecipes must also be a subtype of SimpleFoods,
which means that Pear will be a member. Abstract subclasses and traits do
not have to follow this restriction, but since they cannot be instantiated with
new, there is no risk that the this.Pear reference will fail
### 如何训练自定义的大规模机器学习模型 #### 使用 Scikit-learn 构建基础框架并集成自定义算法 对于构建大规模机器学习模型,可以利用 Scikit-learn 提供的基础架构和工具链作为起点。Scikit-learn 是一个强大的 Python 库,支持多种经典机器学习算法,并且易于与其他库结合使用以实现更复杂的逻辑[^1]。 当面对特定应用场景时,可能需要开发超出标准库范围的功能或优化现有方法。此时可以在 Scikit-learn 的基础上加入自定义组件,比如通过继承 `BaseEstimator` 和 `ClassifierMixin` 类创建新的分类器类,从而允许无缝融入整个工作流之中。 ```python from sklearn.base import BaseEstimator, ClassifierMixin import numpy as np class CustomModel(BaseEstimator, ClassifierMixin): def __init__(self, param_a=0.5, param_b=1e-4): self.param_a = param_a self.param_b = param_b def fit(self, X, y=None): # 实现模型拟合过程 pass def predict(self, X): # 定义预测函数 return np.zeros((X.shape[0], )) ``` #### 利用 Spark MLlib 进行分布式计算 为了处理更大规模的数据集以及加速训练速度,在资源充足的情况下推荐采用 Apache Spark 平台上的 MLlib 工具包来进行分布式的模型训练。Spark 支持多节点集群环境下的高效运算,能够显著提升性能表现特别是针对海量数据场景下[^2]。 具体来说,用户可以选择合适的编程语言(Java/Scala/Python),编写相应的程序读取输入文件、预处理特征向量、调用内置或外部提供的估计器对象执行迭代更新权重操作直至收敛为止;最后保存最终版本到持久化存储介质上以便后续加载应用。 ```scala // Scala 示例代码片段 val trainingData = spark.read.format("libsvm").load("data/mllib/sample_libsvm_data.txt") val lr = new LogisticRegression() lr.setMaxIter(10).setRegParam(0.01) // Fit the model val lrModel = lr.fit(trainingData) ``` #### 借助 PyTorch 扩展复杂度较高的神经网络结构 如果目标是建立具有高度灵活性及表达能力的深层神经网络,则建议考虑基于 PyTorch 框架开展研究与实践。该平台不仅具备动态图机制方便调试修改拓扑关系,而且拥有丰富的社区贡献模块可供选用加快研发进度[^3]。 下面给出一段简单的例子展示怎样快速搭建一个多层感知机用于二元分类任务: ```python import torch import torch.nn as nn import torch.optim as optim class MLP(nn.Module): def __init__(self): super().__init__() self.layers = nn.Sequential( nn.Linear(in_features=784, out_features=256), nn.ReLU(), nn.Linear(in_features=256, out_features=128), nn.ReLU(), nn.Linear(in_features=128, out_features=1), nn.Sigmoid()) def forward(self, x): return self.layers(x) device = 'cuda' if torch.cuda.is_available() else 'cpu' model = MLP().to(device=device) criterion = nn.BCELoss() optimizer = optim.Adam(model.parameters(), lr=1e-3) for epoch in range(num_epochs): for batch_idx, (inputs, targets) in enumerate(train_loader): inputs, targets = inputs.to(device), targets.unsqueeze(-1).type_as(inputs).to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() optimizer.step() print('Finished Training') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值