كيفية إنشاء طريقة Tostring () لائقة () في Scala باستخدام التفكير؟

StackOverflow https://stackoverflow.com/questions/2016499

  •  19-09-2019
  •  | 
  •  

سؤال

لإجراء تأمل في وقت التصحيح في فصول سهلة، أود أن أجعل طريقة شنيعة عامة في الفئة الأساسية للكائنات المعنية. نظرا لأنها ليست في الأداء رمز حاسم، أود استخدام التفكير في طباعة اسم الحقل / أزواج القيمة ("x = 1، y = 2"، إلخ).

هل هناك طريقة سهلة للقيام بذلك؟ جربت عدة حلول محتملة، وركضت ضد قضايا الوصول الأمني، إلخ.

لتكون واضحة، يجب أن تكرر طريقة ToString () في الفئة الأساسية عن فصول عامة في أي فصول ترثت منه، وكذلك أي سمات مختلطة في.

هل كانت مفيدة؟

المحلول

import util._                 // For Scala 2.8.x NameTransformer
import scala.tools.nsc.util._ // For Scala 2.7.x NameTransformer

/**
 * Repeatedly run `f` until it returns None, and assemble results in a Stream.
 */
def unfold[A](a: A, f: A => Option[A]): Stream[A] = {
  Stream.cons(a, f(a).map(unfold(_, f)).getOrElse(Stream.empty))
}

def get[T](f: java.lang.reflect.Field, a: AnyRef): T = {
  f.setAccessible(true)
  f.get(a).asInstanceOf[T]
}

/**
 * @return None if t is null, Some(t) otherwise.
 */
def optNull[T <: AnyRef](t: T): Option[T] = if (t eq null) None else Some(t)

/**
 * @return a Stream starting with the class c and continuing with its superclasses.
 */
def classAndSuperClasses(c: Class[_]): Stream[Class[_]] = unfold[Class[_]](c, (c) => optNull(c.getSuperclass))

def showReflect(a: AnyRef): String = {
  val fields = classAndSuperClasses(a.getClass).flatMap(_.getDeclaredFields).filter(!_.isSynthetic)
  fields.map((f) => NameTransformer.decode(f.getName) + "=" + get(f, a)).mkString(",")
}

// TEST
trait T {
  val t1 = "t1"
}

class Base(val foo: String, val ?? : Int) {
}

class Derived(val d: Int) extends Base("foo", 1) with T

assert(showReflect(new Derived(1)) == "t1=t1,d=1,??=1,foo=foo")

نصائح أخرى

مثال:

override def toString() = {
  getClass().getDeclaredFields().map { field:Field => 
    field.setAccessible(true)
    field.getName() + ": " + field.getType() + " = " + field.get(this).toString()
  }.deepMkString("\n")
}

يستخدم api انعكاس جافا، لذلك لا تنسى استيراد java.lang.reflect._

أيضا، قد تحتاج إلى التقاط itemalaccessException. في Field.get (هذا) يدعو في بعض السيناريوهات، ولكن هذا يعني فقط كنقطة انطلاق.

هل تدرك دروس حالة SCALA الحصول على هذه الطرق التي أنشأها المترجم:

  • Tostring (): سلسلة
  • يساوي (أخرى: أي): منطقية
  • hashcode: int.

كما يحصلون على كائنات مصفاة للبنوك "جديدة أقل" ومطابقة الأنماط.

ولدت toString() يشبه إلى حد كبير الشخص الذي تصفه.

Scala لا يولد أي مجالات عامة. انهم جميعا سيكونان خاصين. طرق الملحقات هي ما سيكون العام، والتفكير في تلك. إعطاء فئة مثل:

class A {
  var x = 5
}

يبدو ByTecode الذي تم إنشاؤه:

private int x;
public void x_$eq(int);
public int x();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top