当前位置: 首页 > 知识库问答 >
问题:

Kotlin中数据类中的私有成员变量

狄望
2023-03-14

我是kotlin的新手,当我阅读kotlin中的数据类时,我发现了这些代码。这基本上是java模型类和kotlin数据类之间的比较,而且这两个代码都执行相同的任务。

代码1

public class VideoGame {

private String name;
private String publisher;
private int reviewScore;

public VideoGame(String name, String publisher, int reviewScore) {
    this.name = name;
    this.publisher = publisher;
    this.reviewScore = reviewScore;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getPublisher() {
    return publisher;
}

public void setPublisher(String publisher) {
    this.publisher = publisher;
}

public int getReviewScore() {
    return reviewScore;
}

public void setReviewScore(int reviewScore) {
    this.reviewScore = reviewScore;
}}

代码2

data class VideoGame(val name: String, val publisher: String, var reviewScore: Int)

我的问题是,在数据类中,所有变量都是公共的而不是私有的,任何人都可以在此类对象的帮助下直接访问变量,但在java代码中,所有变量都是私有的,这就是为什么我们必须为这些成员变量编写getter和setter,如果它是公共的,则不需要getter和setter。那么这些代码是如何相同的呢?

共有2个答案

禄仲渊
2023-03-14

这些函数不执行相同的任务,因为Java版本有getter,而Kotlin版本没有,因为属性是val而不是var。如果它们是var,那么所有功能都会在那里(另外,Kotlin数据类还具有copy功能和equalshashcode,以及为您实现的toString)。

默认情况下(没有自定义getter/setter),静态编程语言属性(公共或非公共)就像具有(公共或非公共)getter和/或setter的Java私有字段。

在Java中,通常不建议将字段公开,这样其他对象就可以直接修改它们。这不是面向未来的,因为如果您决定在更改值时产生副作用,您必须将字段更改为private并添加一个setter。这将破坏与该类一起工作的任何代码。为了避免这种情况,字段应该是私有的,而getters和setters可以是公共的,不幸的是这是一大堆样板代码。

在Kotlin中,您可以使用自定义设置器将默认属性更改为一个属性,并且不会破坏使用它的代码。

易刚捷
2023-03-14

data class的主要用途是简化编写POJO的工作。

如果您进入IDE并编写您的视频游戏类:

data class VideoGame(val name: String, val publisher: String, var reviewScore: Int)

然后你反编译它:

您的 IDE 工具栏

你得到这个:

@Metadata(
   mv = {1, 1, 16},
   bv = {1, 0, 3},
   k = 1,
   d1 = {"\u0000\"\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0002\n\u0002\u0010\b\n\u0002\b\r\n\u0002\u0010\u000b\n\u0002\b\u0004\b\u0086\b\u0018\u00002\u00020\u0001B\u001d\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0003\u0012\u0006\u0010\u0005\u001a\u00020\u0006¢\u0006\u0002\u0010\u0007J\t\u0010\u000f\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0010\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0011\u001a\u00020\u0006HÆ\u0003J'\u0010\u0012\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00032\b\b\u0002\u0010\u0004\u001a\u00020\u00032\b\b\u0002\u0010\u0005\u001a\u00020\u0006HÆ\u0001J\u0013\u0010\u0013\u001a\u00020\u00142\b\u0010\u0015\u001a\u0004\u0018\u00010\u0001HÖ\u0003J\t\u0010\u0016\u001a\u00020\u0006HÖ\u0001J\t\u0010\u0017\u001a\u00020\u0003HÖ\u0001R\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\b\u0010\tR\u0011\u0010\u0004\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\n\u0010\tR\u001a\u0010\u0005\u001a\u00020\u0006X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u000b\u0010\f\"\u0004\b\r\u0010\u000e¨\u0006\u0018"},
   d2 = {"Lcom/yourpackage/VideoGame;", "", "name", "", "publisher", "reviewScore", "", "(Ljava/lang/String;Ljava/lang/String;I)V", "getName", "()Ljava/lang/String;", "getPublisher", "getReviewScore", "()I", "setReviewScore", "(I)V", "component1", "component2", "component3", "copy", "equals", "", "other", "hashCode", "toString", "app"}
)
public final class VideoGame {
   @NotNull
   private final String name;
   @NotNull
   private final String publisher;
   private int reviewScore;

   @NotNull
   public final String getName() {
      return this.name;
   }

   @NotNull
   public final String getPublisher() {
      return this.publisher;
   }

   public final int getReviewScore() {
      return this.reviewScore;
   }

   public final void setReviewScore(int var1) {
      this.reviewScore = var1;
   }

   public VideoGame(@NotNull String name, @NotNull String publisher, int reviewScore) {
      Intrinsics.checkParameterIsNotNull(name, "name");
      Intrinsics.checkParameterIsNotNull(publisher, "publisher");
      super();
      this.name = name;
      this.publisher = publisher;
      this.reviewScore = reviewScore;
   }

   @NotNull
   public final String component1() {
      return this.name;
   }

   @NotNull
   public final String component2() {
      return this.publisher;
   }

   public final int component3() {
      return this.reviewScore;
   }

   @NotNull
   public final VideoGame copy(@NotNull String name, @NotNull String publisher, int reviewScore) {
      Intrinsics.checkParameterIsNotNull(name, "name");
      Intrinsics.checkParameterIsNotNull(publisher, "publisher");
      return new VideoGame(name, publisher, reviewScore);
   }

   // $FF: synthetic method
   public static VideoGame copy$default(VideoGame var0, String var1, String var2, int var3, int var4, Object var5) {
      if ((var4 & 1) != 0) {
         var1 = var0.name;
      }

      if ((var4 & 2) != 0) {
         var2 = var0.publisher;
      }

      if ((var4 & 4) != 0) {
         var3 = var0.reviewScore;
      }

      return var0.copy(var1, var2, var3);
   }

   @NotNull
   public String toString() {
      return "VideoGame(name=" + this.name + ", publisher=" + this.publisher + ", reviewScore=" + this.reviewScore + ")";
   }

   public int hashCode() {
      String var10000 = this.name;
      int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;
      String var10001 = this.publisher;
      return (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31 + this.reviewScore;
   }

   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof VideoGame) {
            VideoGame var2 = (VideoGame)var1;
            if (Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.publisher, var2.publisher) && this.reviewScore == var2.reviewScore) {
               return true;
            }
         }

         return false;
      } else {
         return true;
      }
   }
}

所以支持字段是私有的。静态编程语言正在为你做所有乏味和繁重的工作。那就是:

  1. 使用getter和setter支持字段
  2. toString
  3. 的基本实现
  4. equals
  5. 的实现
  6. hashCode
  7. 的实现
  8. 注释为空
  9. 编写构造函数实现
  10. 添加有用的复制方法

你会得到一个惊人的82行臃肿的代码,你可能会自己写(也许在其中撒上一些错误?)在Java中交换1个关键字。是不是很棒?

  • 数据类简化了POJO的编写
  • val告诉编译器实现给定属性的getter。该属性在类本身中也是不可变的。(您不能在属于该类的函数中更改它)
  • var告诉编译器提供setter和getter
  • 您可以在同一<code>数据类</code>中设置属性的可见性,例如:<code>数据类别MyClass(private val prop:Int)</code>

其他示例:

您在val和var前面使用的关键字只影响getters和setters的可见性。

例如:Public get但private set:

class VideoGame {
      var pegiRating: Int = 0
           private set
}
 类似资料:
  • Singleton设计模式说我们应该在“single instance”类中定义一个私有静态属性。但是,没有适当的解释为什么数据成员必须是私有静态的。如果数据成员只是私有的,会有什么不同吗? 在以下代码中: 如果数据成员不是静态的,会有什么不同吗? 编辑:通过公开析构函数,它会改变单例设计的属性吗?

  • 我正在开发一个使用反射的库,我想操纵给定KClass的所有属性/函数。 使用属性,我可以操作所有可访问的成员(根据留档),即:公共、内部和受保护的字段、属性和函数。但是我看不到私有的。 使用Java反射,我可以使用,同样,我可以看到使用类的私有方法。getDeclaredMethods()。 有没有办法使用kotlin反射API来实现这一点?

  • 我在kotlin中初始化了一些私有Int变量。 我的问题是,当我旋转手机时,会创建一个新的is活动,在当前代码中,分数被分配为0。是否有任何方法可以只初始化一次?出路是什么? 我在使用分数创建内部有一些计算。由于 onRestoreInstanceState 是在 onCreate 之后执行的,除了在 onStart 中定义分数之外,有没有办法保持分数值在屏幕旋转时不受影响?

  • 问题内容: 有人告诉我,对于Java子类,它可以继承其超类的所有成员。那么这是否意味着甚至私人成员?我知道它可以继承受保护的成员。 谁可以给我解释一下这个。我现在很困惑。 问题答案: 不,私有成员 不会被继承, 因为私有成员的范围 仅限 于定义它的类。仅公共成员和受保护成员被继承。 从, 超类私人成员 子类 不继承 其父类 的私有成员 。但是,如果超类具有用于访问其私有字段的公共或受保护的方法,则

  • 因此,我试图用Kotlin开发一个Android应用程序,作为纸笔RPG伴侣。现在我想创造一个暴民阶层 在另一个活动中,我想显示以下信息: Android studio不断告诉我不能访问“名称”:尽管它在“Mob”中是私有的。我以为这就是我得到< code>get()的原因? 也许有更多静态编程语言经验的人可以帮忙。提前谢谢你。