有特点
trait Persisted {
def id: Long
}
Run Code Online (Sandbox Code Playgroud)
如何实现一个接受任何case类实例的方法并返回其特征混合的副本?
该方法的签名如下:
def toPersisted[T](instance: T, id: Long): T with Persisted
Run Code Online (Sandbox Code Playgroud) 如何获得Box<B>或&B或&Box<B>从a在此代码变量:
trait A {}
struct B;
impl A for B {}
fn main() {
let mut a: Box<dyn A> = Box::new(B);
let b = a as Box<B>;
}
Run Code Online (Sandbox Code Playgroud)
此代码返回错误:
error[E0605]: non-primitive cast: `std::boxed::Box<dyn A>` as `std::boxed::Box<B>`
--> src/main.rs:8:13
|
8 | let b = a as Box<B>;
| ^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
Run Code Online (Sandbox Code Playgroud) 在Rust中,抽象的主要工具是traits。在C ++中,有两种用于抽象的工具:抽象类和模板。为了摆脱一些使用模板的缺点(例如,硬盘读取错误消息),C ++引入的概念,这是“命名集的要求”。
这两个功能似乎非常相似:
但据我了解,也存在显着差异。例如,C ++的概念似乎定义了一组必须有效的表达式,而不是列出函数签名。但是那里有很多不同且令人困惑的信息(也许是因为概念仅出现在C ++ 20中?)。这就是为什么我想知道:C ++概念和Rust的特性之间的区别和相似之处到底是什么?
是否存在仅概念或特征提供的功能?例如,Rust的关联类型和const如何?还是用多个特征/概念来界定一个类型?
我正在设计一个类层次结构,它由一个基类和几个特征组成.基类提供了几种方法的默认实现,并且traits选择性地覆盖某些方法abstract override,以便充当可堆叠的traits/mixins.
从设计的角度来看,这很有效,并映射到域,以便我可以从这里添加过滤函数(一个特征),带有来自此处的谓词(另一个特征)等.
但是,现在我想要一些我的特征来采用隐式参数.我很高兴从设计的角度来看这仍然有意义,并且在实践中不会让人感到困惑.但是,我不能说服编译器运行它.
问题的核心似乎是我无法为特征提供构造函数参数,因此可以将它们标记为隐式.在方法实现中引用隐式参数无法使用预期的"无法找到隐式值"消息进行编译; 我试图通过构建阶段(在实践中,它总是在范围内)"隐藏"隐含的方法,以便在方法中可用
implicit val e = implicitly[ClassName]
Run Code Online (Sandbox Code Playgroud)
但是(毫无疑问,你们很多人都希望)这个定义失败了同样的信息.
似乎这里的问题是我无法说服编译器用implicit ClassName标志标记特征本身的签名,并强制调用者(即将特征混合到一个对象中的那些)来提供隐式.目前我的调用者正在这样做,但编译器没有在此级别进行检查.
是否有任何方法可以将特征标记为在施工时需要某些隐含物?
(如果不是,这还没有实现,还是有更深层次的原因,为什么这是不切实际的?)
我想知道是否有关于如何对PHP特征进行单元测试的解决方案.
我知道我们可以测试一个使用该特性的类,但我想知道是否有更好的方法.
在此先感谢任何建议:)
编辑
另一种方法是在测试类本身中使用Trait,因为我将展示下面的内容.
但我并不热衷于这种方法,因为没有保证在特征,类和PHPUnit_Framework_TestCase(在本例中)之间没有类似的方法名称:
这是一个示例特征:
trait IndexableTrait
{
/** @var int */
private $index;
/**
* @param $index
* @return $this
* @throw \InvalidArgumentException
*/
public function setIndex($index)
{
if (false === filter_var($index, FILTER_VALIDATE_INT)) {
throw new \InvalidArgumentException('$index must be integer.');
}
$this->index = $index;
return $this;
}
/**
* @return int|null
*/
public function getIndex()
{
return $this->index;
}
}
Run Code Online (Sandbox Code Playgroud)
及其测试:
class TheAboveTraitTest extends \PHPUnit_Framework_TestCase
{
use TheAboveTrait;
public function test_indexSetterAndGetter()
{
$this->setIndex(123);
$this->assertEquals(123, …Run Code Online (Sandbox Code Playgroud) 如何使用同名方法处理特征?
trait FooTrait {
public function fooMethod() {
return 'foo method';
}
public function getRow() {
return 'foo row';
}
}
trait TooTrait {
public function tooMethod() {
return 'too method';
}
public function getRow() {
return 'too row';
}
}
class Boo
{
use FooTrait;
use TooTrait;
public function booMethod() {
return $this->fooMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
错误,
致命错误:特征方法getRow尚未应用,因为在Boo中存在与其他特征方法的冲突...
我该怎么办呢?
而且,使用两个相同的方法名称,我如何从中获取方法trait FooTrait?
$a = new Boo;
var_dump($a->getRow()); // Fatal error: Call to undefined method Boo::getRow() in...
Run Code Online (Sandbox Code Playgroud)
编辑: …
在我看来,Rust 和traitJava 是一样的interface——一组需要在对象上实现的函数。
trait没有命名它是出于技术原因interface还是只是出于某种偏好?
我已经阅读过Scala,通常建议使用Traits而不是Abstract类来扩展基类.
以下是一个很好的设计模式和布局吗?这是Traits如何取代Abstract?
我刚刚开始学习Scala,我正在遵循的许多教程都使用了一种main方法的不同表示形式的组合.除了熟悉的主要方法; 还有使用特征App或Application.它似乎Application已被弃用,不推荐使用,但我找不到任何有关这些定义入口点的方法的信息.
所以,我想知道是否有人可以向我解释:
App和Application工作如何?Application不再推荐这个App特性,这个特性有什么不同呢?App来启动我的程序?这两种方法有什么区别?traits ×10
rust ×4
scala ×4
php ×2
abstract ×1
c++ ×1
c++-concepts ×1
case-class ×1
implicit ×1
interface ×1
mixins ×1
php-5.5 ×1
phpunit ×1
unit-testing ×1